but that link gave me "File not found". Could you please attach it here or give a working link? I am making a plugin of my own and would just want to do some comparison, so if it is difficult please just forget this.
And it seems to me that for closed strokes the old plugin may have a little bug. The results differed slightly from those of the plugin I am now developing, and that made me notice the following. Look at the picture:
The blue triangle is the original path and the red path is what the old plugin made. The two handles shown belong to the red path. Notice that they are not along the same line. They form an angle, so the path is not smooth there. That problem anchor appears as the first anchor in the list of control points (checked in the Python console).
I know very well by now that closed strokes are difficult for plugin authors. The start and end anchors require special handling, and it is always an effort to get it all right.
Yes, I am developing a similar plugin right now. Instead of C2-continuity it makes also less restrictive G2-continuous paths. I shall publish it when (and if) I can get it in a form that satisfies myself. Let us hope for the best.
Is the "C2-continuity" more constraining than having the two tangents colinear and symmetric (what you get by depressing the shift key when moving tangents)? Because experimentally this alone doesn't define a single solution.
(02-25-2022, 12:30 PM)Ofnuts Wrote: Is the "C2-continuity" more constraining than having the two tangents colinear and symmetric (what you get by depressing the shift key when moving tangents)? Because experimentally this alone doesn't define a single solution.
This is not my line of expertise, but I try to answer as I understand it.
Short answer: Having the two tangents collinear and symmetric means C1-continuity. The C2-continuity is more constraining in that it brings in an additional condition on curvature.
Long answer: A stroke of a path defines a parametric curve, that is, a function f(t) from some real interval to the plane. You can think that we take the parametric representations P(t) of the individual Bezier segments (each one between two anchors), and from those P(t)'s we compose the f(t) in a certain manner. (I can expand this more in detail if you like.) Then:
C1-continuity means that the first derivative f'(t) is continuous everywhere.
C2-continuity means that the first and second derivatives f'(t) and f''(t) are continuous everywhere.
Since the P(t)'s are polynomials and have all derivatives continuous the only points where C1- or C2-continuity can fail are the anchors where we change from one Bezier segment to the next.
So let us look at one anchor A. There two Bezier segments meet, let us call them "left segment" and "right segment". Let the left segment have control points p0,p1,p2,p3 and the right segment q0,q1,q2,q3. Then p3=q0=A.
Let P(t) and Q(t) be the functions of the two segments (the polynomials of degree 3 involving the Bernstein polynomials). We know that the derivatives at A are: P'(1) = 3*(-p2+p3) and Q'(0)=3*(-q0+q1). That is, the derivatives are equal to 3 times the handles (ignoring the directions).
C1-continuity means that P'(1) = Q'(0), or -p2+p3 = -q0+q1, which means precisely that the two handles at A are collinear and symmetric.
C2-continuity requires that in addition P''(1) = Q''(0). I mention only that P''(1) = 6*(p1-2*p2+p3) and Q''(0) = 6*(q0-2*q1+q2) and go no further. But you see that this means an extra condition involving the anchor A=p3=q0 and two more control points on both sides of A.
So, in the problem case in post #5, even C1-continuity does not hold.
Yes, C1-continuity does not define only a single solution (if I understand right you last remark). But the point in Stuart Kent's text (link in post #5) is that if we require C2-continuity and in addition that f''(t)=0 at the start and end of the stroke, then the solution exists and is unique. Kent derives a big matrix equation which gives the solution.
(02-25-2022, 12:30 PM)Ofnuts Wrote: Is the "C2-continuity" more constraining than having the two tangents colinear and symmetric (what you get by depressing the shift key when moving tangents)? Because experimentally this alone doesn't define a single solution.
This is not my line of expertise, but I try to answer as I understand it.
Short answer: Having the two tangents collinear and symmetric means C1-continuity. The C2-continuity is more constraining in that it brings in an additional condition on curvature.
Long answer: A stroke of a path defines a parametric curve, that is, a function f(t) from some real interval to the plane. You can think that we take the parametric representations P(t) of the individual Bezier segments (each one between two anchors), and from those P(t)'s we compose the f(t) in a certain manner. (I can expand this more in detail if you like.) Then:
C1-continuity means that the first derivative f'(t) is continuous everywhere.
C2-continuity means that the first and second derivatives f'(t) and f''(t) are continuous everywhere.
Since the P(t)'s are polynomials and have all derivatives continuous the only points where C1- or C2-continuity can fail are the anchors where we change from one Bezier segment to the next.
So let us look at one anchor A. There two Bezier segments meet, let us call them "left segment" and "right segment". Let the left segment have control points p0,p1,p2,p3 and the right segment q0,q1,q2,q3. Then p3=q0=A.
Let P(t) and Q(t) be the functions of the two segments (the polynomials of degree 3 involving the Bernstein polynomials). We know that the derivatives at A are: P'(1) = 3*(-p2+p3) and Q'(0)=3*(-q0+q1). That is, the derivatives are equal to 3 times the handles (ignoring the directions).
C1-continuity means that P'(1) = Q'(0), or -p2+p3 = -q0+q1, which means precisely that the two handles at A are collinear and symmetric.
C2-continuity requires that in addition P''(1) = Q''(0). I mention only that P''(1) = 6*(p1-2*p2+p3) and Q''(0) = 6*(q0-2*q1+q2) and go no further. But you see that this means an extra condition involving the anchor A=p3=q0 and two more control points on both sides of A.
So, in the problem case in post #5, even C1-continuity does not hold.
Yes, C1-continuity does not define only a single solution (if I understand right you last remark). But the point in Stuart Kent's text (link in post #5) is that if we require C2-continuity and in addition that f''(t)=0 at the start and end of the stroke, then the solution exists and is unique. Kent derives a big matrix equation which gives the solution.
So, to have a proper smooth "closure", we would just require that f"(0.0 on first spline)==f"(1.0 on last spline)?
Didn't dig too much in the code of the current smooth plugin, but I would guess that it splits a stroke into several splines if there are angles that aren't smoothed, smoothes these individually, and then splice them back, throwing away the "external" handle so if there is at least one unprocessed angle in the stroke, everything is fine...
(02-25-2022, 05:17 PM)Ofnuts Wrote: So, to have a proper smooth "closure", we would just require that f"(0.0 on first spline)==f"(1.0 on last spline)?
Didn't dig too much in the code of the current smooth plugin, but I would guess that it splits a stroke into several splines if there are angles that aren't smoothed, smoothes these individually, and then splice them back, throwing away the "external" handle so if there is at least one unprocessed angle in the stroke, everything is fine...
To get a smooth "closure" also the first derivatives have to be equal.
I haven't looked at the code at all but what you suggest seems reasonable.
Didn't dig too much in the code of the current smooth plugin, but I would guess that it splits a stroke into several splines if there are angles that aren't smoothed, smoothes these individually, and then splice them back, throwing away the "external" handle so if there is at least one unprocessed angle in the stroke, everything is fine...
Ofnuts, a small puzzle, not that this matters much, just out of curiosity it would be nice to know. Please don't bother to use any more time on this. I know that I don't. Sorry for this waste of bandwidth.
I think that the plugin does not work in that natural way to leave some corners unprocessed. I haven't looked at the code but I made the following experiments. I made the straight-edge figure on the left:
Then I made two experiments:
I called smooth-path.exe so that it left the sharpest corner C unprocessed (it smoothed only corners between 90 and 180 degrees). The result is the blue path on the right.
I cut the straight-edge path into two strokes at C. (I created an extra anchor near C, deleted the small edge in between, by 'snap to grid' moved the new anchor to C, carefully collapsed all handles to 0.) Either stroke had C as an end point. Then I called the plugin. The result is the red path on the right.
If the plugin worked as you suggested the results should be the same I think. They are not. Either I don't understand this right or some different logic is applied when a corner has to be left unprocessed.
In experiment 1 the created path has zero handles at C. In experiment 2 the handles are non-zero.
I also repeated experiment 2 with my own plugin which I am currently developing and uses the same idea (C2-continuity and f''(t)=0 at stroke ends). The result was quite identical with the red path.