From: Jasper van de Gronde <th.gronde@hc...>  20121016 11:43:42

On 121012 23:11, Johan Engelen wrote: > On 12102012 14:59, Jasper van de Gronde wrote: >> ... >> To deal with zerolength handles, the easiest (and correct) method is >> probably to specify that the curvature is zero at the endpoint with the >> zerolength handle (if both handles are zerolength, then the Bézier >> curve forms a line segment). That this is correct can be derived from >> the fact that the unit tangent vector at the endpoint with a zerolength >> handle points in the same direction as the second derivative (so locally >> it's a straight line). This is a consequence of l'Hôpital's rule btw. > > I don't think this is correct. That observation /is/ :) Note that the case of two zerolength handles or two coinciding handles of which one has zerolength gives a straight line (segment), though. So for that case it makes perfect sense to have zero curvature throughout (and this actually follows from the description below). > It is possible to make segments with and > without a zerolength handle that look exactly the same. It should not be, in general. (Fewer degrees of freedom.) > Also, as you > are moving the handle closer and closer to the knot, it does not > converge to zero curvature, in fact it tends to lead to higher curvature > instead of lower curvature. There is essentially a bit of instability here. Yes, if you approach it from most angles, then the curvature increases. However, if you follow l'Hôpital's rule to compute the unit tangent vector at t=0 (so the derivative divided by the norm of the derivative), or (which is a bit easier), the derivative of y w.r.t. x, then you see that the unit tangent vector at t=0 points to the second handle. If you then take the limit as P2 approaches P1 from the direction of P2 (or opposite), you get zero curvature. Also (just as an observation), as the handle gets smaller, its influence decreases. So although locally you have a very large curvature, it's only over a very small portion of the curve. > Wouldn't l'Hopital imply that you can get > away by using +1 higher derivs instead? You're completely right. (If you intended taking the derivative of the numerator and denominator and dividing those.) However, higher derivatives can (and will) still be zero in this case, so this complicates things a bit. However, if you make the first handle zerolength, and then compute the limit of the curvature as t goes to zero, then you find that the curvature is equal to det([P3P1,P4P1]) divided by something that is zero at t=0 and positive for t slightly above zero, as long as P3P1 is not zerolength. Thus, if det([P3P1,P4P1])=0, (all points and handles on a line), then the curvature at t=0 is zero, and otherwise it is infinite with the sign of det([P3P1,P4P1]). So, I stand corrected, the rule isn't zerolength=zerocurvature, but rather, a zerolength P1P0 implies that the curvature at P0 is either infinity, zero or +infinity, depending on the sign of det([P3P1,P4P1])=0. (Assuming at least some point does not coincide with P1.) >> ... >> One possible way to specify the restriction for this kind of join would >> be to limit the arclength on either side of the join. The main problem >> is then joining the end points, as a line segment between the two is not >> guaranteed to not intersect the circles. Some experimentation suggests >> that it might be possible to define a sensible boundary using >> interpolation between the two end points that is guaranteed not to >> intersect either of the circles. > > I have no clue what you are saying here. :) Okay, turns out my assumption about how miterlimit worked was wrong, but I still think it makes sense. Basically, when using a miter join, the miter can get infinitely large. This causes all sorts of problems, so "miterlimit" was introduced. Basically this says: "a miter larger than so and so can't be good". The solution then is to fall back to a bevel join... I had assumed it would just "cap" the miter (as this would still prevent it from being insanely large, while preventing a sudden jump from miter to bevel). For the moment, assume that SVG had chosen to simply "cap" the miter. For example, one could restrict the length of both sides of the miter to the miterlimit and draw a straight line between the two. This should cause no further problems (at least in rendering, maybe there are other issues that caused the committee to not go down this route). Now, when joining using arcs, it seems to make even more sense to simply "cap" the join. Otherwise you can have a nice curved join one minute and a bevel (or miter) join the next, seems a bit weird to me. So suppose that you simply "cap" the join. How do you go about capping it? That brings us back to what I was saying. Because both sides of the join are curved, there is no guarantee that a straight line between the endpoints (of the limited sides of the join) does not cross either side of the join (which I think would look really weird). So you want some other kind of "cap". This is why I took a short look into finding a sensible cap by interpolating between both arcs. This looks promising, but a straightforward interpolation between the two arcs still has some problems. But feel free to ignore these fine points, the gist is that if one wanted to "cap" the join instead of falling back to a miter or bevel (and introducing discontinuous/unstable behaviour), then some thought needs to go into how to actually cap it. But of course it might just be simplest to fall back to a miter or bevel. 