CreativeInquiry / PEmbroider

Embroidery Library for Processing
Other
443 stars 28 forks source link

Satin Hatch Centerline #82

Closed tatyanade closed 3 years ago

tatyanade commented 3 years ago

This issue came up in the slack earlier but optimize sometimes causes the shape's centerline to stitch on top of the fill pattern - this happens with satin_hatching_2 and mainly happens when there are multiple shapes on the canvas (haven't had the issue with just one shape) & can be avoided when only using satin fill by not calling optimize; issue seems to be that optimize doesn't place priority on making sure center-line is stitched before the rest of fill.

LingDong- commented 3 years ago

Our TSP algorithm is written under the fundamental assumption that every polyline is reversible, so it can find the best possible route. The system stores all drawing as polylines, and it's unaware what fill method you were using when you created the shape, so it's also difficult to somehow inform the TSP to make exceptions.

I think the easiest and best solution is to not run optimize() on SATIN results, since SATIN already optimizes the stroke order, and it does so better than TSP.

golanlevin commented 3 years ago

Right, but what happens if someone has a design that combines SATIN with other elements, and then tries to optimize at the end? :(

What if there were an additional flag settable for every stitch, which was whether or not it was reversible?

LingDong- commented 3 years ago

Sure I can add it. It's just a ton of book keeping.

We have some 50 function that deals with the global set of polylines, each function will now have to push/remove/modify a bool in another large array of flags each indicating whether the corresponding polyline is reversible. Some of these functions deal with the polylines in non-trivial ways, generating/splitting/merging a lot of polylines and now each of them has to correctly handle the list of reversible-ness in parallel.

Another equally painful option is that we extend the ArrayList<PVector> class, so each polyline will now be stored as a polyline + a flag. But we then need to also modify every function that deals with ANY polyline, which is literarily every function in the library.

As usual I'm happy to work on it, just want to let you know it's complicated before I start :)

golanlevin commented 3 years ago

OK, hm.

So, is there a way to use the beginOptimize()/endOptimize() commands, so that we can make this the user's problem?

By the way, I don't see beginOptimize()/endOptimize() in the API document (https://github.com/CreativeInquiry/PEmbroider/blob/master/API.md), is there a reason they don't show up?

Let's sit on this for a couple of days and come back to it. Perhaps we will have another idea.

LingDong- commented 3 years ago

Hi @golanlevin

beginOptimize()/endOptimize() don't show up in the API document because they're not not documented in the source code -- I added their documentation and regenerated the API: 247f08948c826d681cee95a539cf31b7bc4252b3

Yes, user can use these functions to skip SATIN stitches, e.g.

E.beginOptimize();
E.hatchMode(E.CONCENTRIC);
// draw stuff here
E.endOptimize();

E.hatchMode(E.SATIN);
// draw stuff here
// won't be optimized

E.beginOptimize();
E.hatchMode(E.CONCENTRIC);
// draw stuff here
E.endOptimize();

Another more hacky way is to utilize the fact that stitches of different colors are optimized separately

E.fill(0);
E.hatchMode(E.CONCENTRIC);
// draw stuff here

E.fill(255,0,255); // obnoxious magenta to be replaced later
E.hatchMode(E.SATIN);
// draw stuff here
int index = E.polylines.size()-1; // save the index to re-color it later

E.fill(0);
E.hatchMode(E.CONCENTRIC);
// draw stuff here

E.optimize();

E.colors.set(index, 0x000000); // the actual desired color in hex
golanlevin commented 3 years ago

Thanks, @LingDong- -- could you kindly inform our beta tester in the Slack about this solution. I'm happy with it and I feel the matter is closed. Also, thanks for updating the API.

LingDong- commented 3 years ago

Thanks @golanlevin, I've updated the slack channel with a link to this issue.

I think there might yet be a more elegant way to do this, I'll keep thinking about it