This is Words and Buttons Online — a collection of interactive #tutorials, #demos, and #quizzes about #mathematics, #algorithms and #programming.

Can we use lemniscates for ultra-cheap vector graphics?

TL&DR: Yes, but you get what you pay for.

I stole this idea from an old Russian book named Notable Curves by Alekséi Markushévich. The book was published in 1952 and, as you can imagine, it has nothing to do with computer graphics at all.

In that book, however, was a casual mention of a mathematical proof that the multifocal lemniscate can approximate any possible curve with some given error. There were also some promising but frankly unrealistic pictures of a man's face and a bird, both produced by lemniscates with a handful of foci.

Which got me thinking. SVG is relatively cheap memory-wise but this looks even cheaper. For instance, to approximate just a piece of a curve with the Bézier cubic, you already have to store 4 points somewhere. With the lemniscate, you can approximate a whole face or a bird with only 6 or 7 points. Isn't it wonderful?! Almost too good to be true, right?

Multifocal lemniscate

A lemniscate is an isoline of the product of distances to the foci. First, you set some n points xi you call foci, then you build a function that for any point x, computes all the distances to the foci, and multiply them together. Where your function meets some number — there is your curve.

|x - x1| × |x - x2| × ... × |x - xn| = ρ

As it turns out, this is not too handy to play with since you have to adjust the ρ every time you add or remove a point. It is a little irritating so I changed the formula just a bit to make it more practical.

|x - x1| × |x - x2| × ... × |x - xn| = r n

Now you can add and remove points without readjusting the r.

I've made a mini-editor for lemniscate graphics with a few examples. Feel free to explore!




   

You can export your image into a set of points, and reimport it back.

Ok, so it's not that easy to make it draw exactly what you want it to. It is mathematically possible to draw everything, sure, but pragmatically, it only makes sense to draw the simplest shapes with this tool. With a limited set of points, it's not very powerful, and with adding more and more points, it gets less and less user-friendly.

But what about image tracing? Shouldn't it automagically turn poorly pixelated pictures into nice and smooth vector images?

Well, yes and no. With lemniscate approximating a pixel image, the error function is not very friendly to the gradient descent method. There are some seemingly random platoes and points masquerading as local minimums that make the minimizer stall every now and then. I tried a few approaches but, apparently, a simple random crawler works the best.

And this “the best” is still not very good.

Here's my tracer. It minimizes the error function one small step at a time, making the vector image closer to the pixelated original. If you're not afraid to put your browser into a coma, you can ask for drastically more iterations or raise the step size.


,    

Of course, you're more than welcome to explore it further! You can start from the code for this very page available on GitHub. Besides, multifocal lemniscate is a very simple concept, it all revolves around one simple formula. You can easily reimplement it in your exploration environment of choice.

Conclusion

The practicality of this approach is limited. For real-world vector graphics, its application is doubtful. It's way easier to approximate curves with splines of all kinds both automatically and manually.

But when you're really constrained by memory, and a badly drawn cat of 19 bytes is a wanted alternative for a nice cat of a few kilobytes, then yes — multifocal lemniscate is your friend. For instance, it might give you an advantage in the js13kGames or the js1024 competition.