Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify curves like Paper.js or vectorscribes "smart remove brush tool" does. #411

Open
Quentie opened this issue Aug 3, 2015 · 13 comments · May be fixed by #1698
Open

Simplify curves like Paper.js or vectorscribes "smart remove brush tool" does. #411

Quentie opened this issue Aug 3, 2015 · 13 comments · May be fixed by #1698

Comments

@Quentie
Copy link

Quentie commented Aug 3, 2015

Maybe a curve could be approximated (so that optionally you loose some detail?).

svgo already did an amazing job minimizing a test svg of mine (170kb => 22kb), but hey you can always ask for more ;)

@GreLI
Copy link
Member

GreLI commented Aug 3, 2015

Yep, I was thinking about it, but haven't got to it yet. Many plans, but very little time.

@waldyrious
Copy link
Contributor

I suppose this is at least related to Inkscape's "simplify", right?

@Quentie
Copy link
Author

Quentie commented Aug 3, 2015

@waldyrious Yes this looks like what I was thinking off ...

@GreLI
Copy link
Member

GreLI commented Aug 4, 2015

May be you were meant Illustrator? Inkscape is quite bad here.

@Quentie
Copy link
Author

Quentie commented Aug 4, 2015

I have not tested inkscape's 'simplify' (just had a look at their user manual to see what waldyrious was talking about...).
Just wanted to say that this is generally what I was thinking about (no clue, if it is implemented in a good or bad way).

@hugolpz
Copy link
Contributor

hugolpz commented Dec 24, 2015

You have http://bost.ocks.org/mike/simplify/ which has some witty js code for line simplification.

@GreLI
Copy link
Member

GreLI commented Dec 25, 2015

Line simplification isn't an issue, actually. Lines takes only 1 pair coordinates, while curves takes 3. Sometimes, it only takes one number (horizontal or vertical line). So one curve is 3 times larger. And there are rarely images which actually needs line simplification, while there are image that may have too many curves and can be simplified without a notable loss.

@behdad
Copy link

behdad commented Feb 10, 2016

Here's paper.js's curve simplify in action:

http://paperjs.org/examples/path-simplification/
https://github.com/paperjs/paper.js/blob/develop/src/path/PathFitter.js
http://paperjs.org/reference/path/#simplify

Should be rather trivial to integrate into a plugin.

@waldyrious
Copy link
Contributor

@GreLI a single curve is 3 times larger than a single line, but to get even an approximation to such a curve, one would need multiple lines, not 1. So for similar geometry, whether it's represented as curves or lines, actually the lines version occupies much more space.

Of course, simplifying curves (which can at least make a reasonable attempt at preserving the shape of the curve while using less nodes) will generally produce more visually appealing results than simplifying the equivalent sequence of lines into a sequence with less nodes. The ideal approach would be to simplify sequences of lines into curves, which can then try to trace the original path by clever usage of the curve parameters.

@jeromew
Copy link

jeromew commented Mar 8, 2017

for reference, this module seem to also approximate a linestring with bezier curves - https://www.npmjs.com/package/turf-bezier

@jeromew
Copy link

jeromew commented Mar 9, 2017

I post this in case someone wants to work on this for svgo (I only discovered svgo via this github issue).

Here is the smallest (server-side + canvas-less) sequence I could find to use the PathFitter of paper.js mentioned by @behdad in order to approximate a path with curves. The compression results are indeed impressive even for complex linestrings and high tolerance.

var paper = require('paper');
paper.setup();
var parser = require('html-attribute-parser')
var tolerance = 0.01;
var d_source = "M20,20L80,80L140,20Z";
var path = new paper.Path({pathData: d_source })
path.simplify(tolerance);
var svg = path.exportSVG({ asString: true});
var d_target = parser(svg).attributes.d

@twardoch
Copy link

I looks like a very low-hanging fruit to use the model of the convertPathData plugin and to incorporate the above minimal example that uses paper. The convertPathData plugin already has the code that allows you to isolate any given d string, and then the above example does the rest. The tolerance could be in the plugin parameters.

I’m not a JS dev at all, but for anyone familiar with JS, it’d be a 10-minute job to create a simplifyPaths.js plugin for svgo that simply relies on paper.js and does just that!

@MarcelRobitaille
Copy link

I opened a pull request that adds this feature based on the code that @jeromew proposed. Definitely took a lot longer than 10 minutes though 😵‍💫

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
8 participants