Plotting mathematical functions without rendering artefacts
I don't think there's a good answer to this, but I'd like to find out if there's a better way to do this.
I need to plot a mathematical function, which is nearly flat at one end of the display, and nearly vertical at the other end. The bottom left quadrant of a circle would be a good model. I can auto-generate as many points as required.
The problem is, I can't do this without all sorts of artefacts.
I haven't tried Bezier fitting; I don't think this would be even close. My understanding is that Bezier is for one-off manually-constructed pretty graphics, and not for real curve-fitting.
That leaves polylines. There are only 2 things I can do with polylines - I can select the line length (in other words, the number of points I auto-generate), and I ca开发者_开发技巧n disable anti-aliasing (setAttributeNS(null, "shape-rendering", "crisp-edges").
If I generate lots of points, then I get jaggies everywhere, and the result is unusable. It can also look very much like it's oscillating, which makes it appear that I've incorrectly calculated the function. The anti-aliasing doesn't make any difference, since it doesn't operate across point boundaries.
The only solution I've got is to draw fewer points, so that it's obvious that I'm drawing segments. It's no longer smooth, but at least there are no jaggies or oscillation. I draw this with the default anti-aliasing.
Any ideas?
Edit: It seems like the only answer to this is actually Bezier curve fitting. You have to preprocess to find the parameters of the required segments, and then plot the results. Google comes up with a number of hits on curve fitting with Beziers.
You have the mathematical function, and can therefore generate as many points as you need.
I assume the problem is that because you do not know the output resolution (SVG is device independent) you do not know how many points to generate. Otherwise you could just create a polyline where each line is approximately 1 pixel long.
Fitting your mathematical function to a bezier curve is (probably) not going to get a perfect match - just like a circle cannot be matched perfectly by a cubic bezier curve. And I think the task of fitting your function to a bezier curve would not be trivial (I've never done this).
Could you rather output your mathematical function to a canvas element? Then you could write some javascript code to plot your mathematical function dependant on the output resolution. Similar to how a graphics system renders a Bezier curve.
Do you know how graphics systems render Bezier curves? They approximate the bezier curve with a polyline, and then measure the error difference between the polyline and the bezier curve. If the difference is greater than a certain tolerance - where the tolerance is determined by the output resolution - the bezier is subdivided and the process repeated for each bezier curve. When the difference between beziers and polylines is below the tolerance, the polylines are drawn. http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Computer_graphics
I suppose you want to draw y=f(x) over a certain interval [a,b]
A classical solution is to take N points uniformly distributed over [a,b], to compute f over these points and draw lines (or polynoms).
It of course doesn't work in your case, since y is nearly vertical in certain area. But why don't you take more points in these areas (and less points where the function is nearly horizontal) ?
You can compute the derivative of your function (or approximate this derivative with (f(x+h)-f(x))/h and h small) and determine the step between two successive points with this derivative
精彩评论