paperjs / paper.js

The Swiss Army Knife of Vector Graphics Scripting – Scriptographer ported to JavaScript and the browser, using HTML5 Canvas. Created by @lehni & @puckey
http://paperjs.org
Other
14.45k stars 1.22k forks source link

Define boolean operation behavior with open paths #757

Closed Pomax closed 8 years ago

Pomax commented 9 years ago

The following code has some interesting, and wrong, union behaviour:

var c1 = new Path("M 300 60 C 430 60 430 140 300 240 C 165 140 165 60 300 60");
var c2 = new Path("M 300 180 C 430 345 430 480 300 480 C 170 480 170 345 300 180");
var c3 = c1.unite(c2);
c1.strokeColor = 'black';
c2.strokeColor = 'black';
c3.fillColor = 'red';

result:

screenshot 81

Pomax commented 9 years ago

and right after filing that I notice there are no z statements in the sub paths... so that might be a problem.

Pomax commented 9 years ago

totally the issue. Closing.

lehni commented 9 years ago

Oh, so it was happening because the paths were open? That should be handled differently in the library still, i think?

Pomax commented 9 years ago

I guess that depends on whether it should treat paths as closed when it performs the boolean operation. It might make sense to force-close paths if unite/intersection etc. are called, since those operations have technically no meaning on open paths.

lehni commented 9 years ago

Yeah... Or we could define what is supposed to happen, e.g. intersecting a closed path with an open path could split the open path along the intersections and erase the bits that lie outside the closed path. This would actually be very useful for hatching and such, and not hard to implement at all... subtract() would do the opposite of that (remove the bits that are inside the closed path). All other operations wouldn't be defined and should probably throw an error. The same is true for all operations when performing them with a closed path on the left and an open path on the right hand side.

Pomax commented 9 years ago

that would be pretty cool, now that you describe it.

lehni commented 8 years ago

Here an example that then should work as described above:

http://sketch.paperjs.org/#S/bVJNc4IwEP0rO1zEkUGUesH20PHWU6c99AAcEFZIhcTZRHtw/O/daMTSIZdM3nu7bz9y9mTRoZd4n3s0ZeMFXqkq+z4VBISlgReQ+APvhWnCD34Xsm7RP2cS+OxIdQmkiygKYLmK8uAGG8VgvGIwfoDakNrjRrWKEpgQVpNMXqbrTGbSerVC4h+vu4PGukNpNCe8AfY4w6jPfQOt4dM/cDmmXI4p4zFlfFc+sPkcUtecFUPqwpxkvN1te8Rhv4Sa27Vdh0IaJM2z9e3AAzi74AQMHRH+BJWNaCtCyZEcHxJ26oQbB/pWZ1U7Qdru7a5Oo5yZnSLwLS2YWqz5eu4VYYuyNg2Ds9kU7su1acJvJaTfZxK5NblwtisppEYyr1uugmvXlnvU5bsn213V1y4srdH06x1MqSZEORkM8EtUpklgNZxqcbBfSB1lNVS/cbE948bNX3pLWOwPzBntJWl++QU=

Pomax commented 8 years ago

hm, given the result in that sketch, I'm not sure I could explain why it'd look that way.

lehni commented 8 years ago

Don't worry that's the old code. Things have improved hugely in the Boolean ops since then. I've just put it here for reference as I'm going to implement the behavior for open paths outlined above.

lehni commented 8 years ago

A new release is imminent now. Finally!

lehni commented 8 years ago

I've updated the linked sketch above. With the latest commits in place, here is how the result now looks. The open path (blue) is intersected with a closed path (red). The result is a group of separate paths (the diagonal lines inside the rectangle), which are then joined to one zig-zag line (green). Works like a charm now!

screen shot 2015-10-24 at 22 45 32
techninja commented 8 years ago

Incredible work guys! Wahoo!

:exclamation: :fireworks: :cake: :boom: :open_mouth: :astonished: :exclamation:

Pomax commented 8 years ago

aha! The above link still shows a slightly different capping for me, which could be because of the specific paper.js it's referencing?

screenshot 23

lehni commented 8 years ago

That's because Sketch is still running the old version of the library. I need to update it!

lehni commented 8 years ago

Try again now, with force refresh!

techninja commented 8 years ago

Force refresh was the ticket for me, works great!

Pomax commented 8 years ago

That's pretty sweet @lehni =)

lehni commented 8 years ago

Please note that in order to get this open path / stroke-based behavior, you now need to call it like this:

var res = line.intersect(rect, { stroke: true });