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

Outline does not work for some shapes #493

Open
euglv opened this issue Apr 2, 2021 · 4 comments
Open

Outline does not work for some shapes #493

euglv opened this issue Apr 2, 2021 · 4 comments

Comments

@euglv
Copy link

euglv commented Apr 2, 2021

The library fails to outline this shape:
image
It is represented by the following SVG path: M 120 0 A 100 100 0 0 1 110.86554718017578 45.92201232910156 L 92.38794708251953 38.26835250854492 A 80 80 0 0 1 38.26828384399414 92.38797760009766 L 45.92204666137695 110.86552429199219 A 100 100 0 0 1 0.00000548346952200518 120 L 0.000009139115718426183 200 A 220 220 0 0 0 76.53670501708984 184.77589416503906 L 84.19052124023438 203.25340270996094 A 240 240 0 0 0 203.2534942626953 84.19031524658203 L 184.7759246826172 76.53665924072266 A 220 220 0 0 0 200 0Z

But the very similar shape is outlined successfully:
image
Path: M 120 0 A 100 100 0 0 1 112.76310729980469 41.04243469238281 L 93.96925354003906 34.20203399658203 A 80 80 0 0 1 49.999942779541016 86.60258483886719 L 59.99997329711914 103.92306518554688 A 100 100 0 0 1 20.83777618408203 118.17693328857422 L 34.72963333129883 196.96156311035156 A 220 220 0 0 0 99.99992370605469 173.2051544189453 L 110.0000228881836 190.52554321289062 A 240 240 0 0 0 206.73239135742188 75.24442291259766 L 187.93850708007812 68.40404510498047 A 220 220 0 0 0 200 0Z
The difference between these two shapes is that in the non-working example the straight lines form an angle of 90 degrees, in the working - 80 degrees.

Here is the code I use to create outline:

const makerjs = require("makerjs");

let notworking = 'M 120 0 A 100 100 0 0 1 110.86554718017578 45.92201232910156 L 92.38794708251953 38.26835250854492 A 80 80 0 0 1 38.26828384399414 92.38797760009766 L 45.92204666137695 110.86552429199219 A 100 100 0 0 1 0.00000548346952200518 120 L 0.000009139115718426183 200 A 220 220 0 0 0 76.53670501708984 184.77589416503906 L 84.19052124023438 203.25340270996094 A 240 240 0 0 0 203.2534942626953 84.19031524658203 L 184.7759246826172 76.53665924072266 A 220 220 0 0 0 200 0Z';
let working = 'M 120 0 A 100 100 0 0 1 112.76310729980469 41.04243469238281 L 93.96925354003906 34.20203399658203 A 80 80 0 0 1 49.999942779541016 86.60258483886719 L 59.99997329711914 103.92306518554688 A 100 100 0 0 1 20.83777618408203 118.17693328857422 L 34.72963333129883 196.96156311035156 A 220 220 0 0 0 99.99992370605469 173.2051544189453 L 110.0000228881836 190.52554321289062 A 240 240 0 0 0 206.73239135742188 75.24442291259766 L 187.93850708007812 68.40404510498047 A 220 220 0 0 0 200 0Z';

let input = makerjs.importer.fromSVGPathData(notworking, { bezierAccuracy: 0.001 });
let result = makerjs.model.outline(input, 5, 1);
makerjs.model.simplify(result);
let outlinePath = makerjs.exporter.toSVGPathData(result, false, [0, 0]);
console.log('Not working:\n', {input, result, outlinePath});

input = makerjs.importer.fromSVGPathData(working, { bezierAccuracy: 0.001 });
result = makerjs.model.outline(input, 5, 1);
makerjs.model.simplify(result);
outlinePath = makerjs.exporter.toSVGPathData(result, false, [0, 0]);
console.log('Working:\n', {input, result, outlinePath});
@euglv
Copy link
Author

euglv commented Apr 3, 2021

I have investigated this further and discovered that outlining is not working because of this dot:
image
It is represented by this command in failing SVG path: L 0.000009139115718426183 200
If I change it to L 0 200 then outline works.

@z3dev
Copy link

z3dev commented Apr 3, 2021

Where did the original SVG come from? That’s a lot of precision for an SVG file. Most applications apply rounding.

@euglv
Copy link
Author

euglv commented Apr 3, 2021

I thought that rounding is needed only to save file size. In my case file size is not an issue.
That SVG is generated by me. This precision comes after I split an arc segment into n equal parts. My code is similar to this:

let part = arc.getTotalLength() / n;
let pos = 0;
let path = '';
for (let i = 0; i < n; i++) {
  let {x, y} = arc.getPointAtLength(pos);
  path += ` L ${x} ${y} `;
  // some other code
  // ...
  pos += part;
}

The issue is not in SVG, this command works as expected: makerjs.importer.fromSVGPathData(path, { bezierAccuracy: 0.1 });
The issue is that I have to round numbers before I pass them to makerjs models. Can't find in documentation that I suppose to do this.

And the case of issue is not in arcs. Here is the simplified square path for which the outline is failing:

const makerjs = require("makerjs");

function getOutline(path, size) {
    let input = makerjs.importer.fromSVGPathData(path);
    let result = makerjs.model.outline(input, size, 1);
    makerjs.model.simplify(result);
    return makerjs.exporter.toSVGPathData(result, false, [0, 0]);
}

let testOk = 'M 0 0 L 50.000009 0 L 50 50 L 0 50 Z';
let testUndefined = 'M 0 0 L 50.0000009 0 L 50 50 L 0 50 Z';

console.log({ path: testOk, outline: getOutline(testOk, 5) });
console.log({ path: testUndefined, outline: getOutline(testUndefined, 5) });

@z3dev
Copy link

z3dev commented Apr 3, 2021

Well, yes and no. Obviously, the library internals are having issues with precision. And your examples show that precision is causing issues with representing paths.

I think the last example with the square is really spot on. Hopefully, there’s a way to work around this.

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

No branches or pull requests

2 participants