Thanks for the details.
I implemented centripetal Catmull-Rom interpolation in Inkscape experimental branch yesterday (with start and endnode doubling). If you want to play with it, try LPE Interpolate points or Catmull-Rom interpolation in LPE Powerstroke.
(Side remark: Catmull-Rom paths will probably cause a lot of headaches to mix conveniently with bezier paths in Inkscape/2Geom, because Catmull-Rom "segments" are not independent.)
regards, Johan
On 24-8-2014 22:49, Chris Lilley wrote:
Hello Johan,
Sunday, August 24, 2014, 9:38:55 PM, you wrote:
Hi Chris, Seems like a good change, so it behaves similar to bezier segments. Then my question becomes, how to form the segment between currentPoint(x,y) and (x1,y1)? Is currentPoint(x,y) to be doubled? Would be fine to me.
If the previous curve command provides a tangent and position (e.g. a cubic or quadratic curve) then this is used as a virtual (x-1, y-1). Otherwise, the line cp(x,y) to (x1,y1) is used as the tangent and virtual point (x-1, y-1) is reflected along that line by the euclidian distance between cp(x,y) to (x1,y1).
If that is clear (hopefully) then there is a further refinement; as we are using centrepetial Catmull-Rom the distances are not uniform; in the Centripetal case, each time interval is the square root of the Euclidean distance between the points. http://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline#Methodol...
Centrepetial Catmull-Rom avoids the tendency to form self-intersecting loops if the points are close together (you can see this happen in Doug's dotty example code, also linked from the minutes, which uses uniform Catmull-Rom). http://schepers.cc/svg/path/dotty.svg
The spec will be updated to reflect these decisions in the next few days (as I said these discussion happened Saturday).
The other question is, at which point to stop drawing. I read that people want 2 points to result in a straight line, i.e. M 0,0 r 1,1
Now, you always have two points because current point is one of them, so x1 y1 in the R command is the second. This will give a straight line. Three points (cp plus two in the R command) will give a curve.
I'm thinking this may need an appendix (like the elliptical arc appendix) to explain the general case where there are four points in hand (xi-1 yi-1),(xi yi), (xi+1 yi+1), (xi+2, yi+2) to draw the curve between (xi yi), (xi+1 yi+1) and the degenerate cases near the start and end of the command which require use of currentPoint and also the computation of virtual points so that each curve segment has the required four points.
If all that is clear (please ask if not) then if should be clear that given a single point in the R command:
R(x1,y1)
plus the always existing current point xcp, ycp
there are three cases for joining to the previous path segment:
a) the previous command provides a tangent and distance; these are used to make the virtual first point (using the square root of the distance between the virtual point and xcp, ycp)
b) the previous command provides a tangent only; this plus the reflected distance to x1,y1 are used to make the virtual first point (using the square root of the distance between the virtual point and xcp, ycp)
c) the previous command provides no tangent (e.g M or m); the tangent from xcp,ycp to x1,y1 is used to provide the tangent and the distance (using the square root of the distance between xcp, ycp and x1,y1)
similarly for the last curve segment produced by the R command there are four cases:
a) the next command provides a tangent and distance; these are used to make the virtual last point (using the square root of the distance between the virtual point and y1, y1)
b) the next command provides a tangent only; this plus the reflected distance to xcp,ycp are used to make the virtual first point (using the square root of the distance between the virtual point and x1, y1)
c) the next command provides no tangent (e.g M or m) or no n=tangent and no next point (e.g. no next command); the tangent from x1,y1 xcp,ycp is used to provide the tangent and the distance (using the square root of the distance between xcp, ycp and x1,y1)
If the previous path is case c and the next is also case c, this will result in a straight line because only xcp,ycp and x1,y1 control the curve; the other two points are virtual and unaffected by previous or next path segments. In the other combinations, some sort of curve will be produced. If the previous path is case a and the next is also case a, then the curve will exhibit curve continuity with the previous and next segments.
If that is still clear(!) we can return to the subject of the thread and consider some new closepath command (not Z, lets call it Y) which attempts to close up the path with a curve rather than a straight line segment as Z do.
Like Z, Y takes no arguments. It has available the current point xcp, ycp and also the start of the path xs,ys.
I propose that Y be defined to be equivalent to R (xs,ys). Unless the last path segment is case c and the first path segment is case c, this will result in a curve. (If they are both case c t=you get a line same as Z, so it is at least well defined). If ther last path segment is case a and the first is also case a you will have curve continuity at both ends of the closepath curve. Otherwise, you willat least get a curve rather than a straight line.