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.44k stars 1.22k forks source link

Parametrized stroke outlining / expanding / offsetting #371

Open strandedcity opened 10 years ago

strandedcity commented 10 years ago

I've been following the library for some time, and have started a spare-time project based on it. I've been eagerly interested in the functionality to expand strokes into paths, particularly for bezier curves (where I know the problem is mathematically complex). Has a strategy / timeline for implementation been discussed? I may be able to contribute if new contributors are welcome.

I wasn't sure if the "outline" feature was separate from what I would describe in a CAD world as "offset". Is there some way to get equations for the position of the stroke edge that is not as complex as a full bezier-offset solution? See http://pomax.github.io/bezierinfo/#offsetting for a very detailed explanation of the math involved.

Thanks!

martin19 commented 4 years ago

@lehni: Thanks very much for your work on this. I've got a question/comment about your offset code posted above: If I understand correctly the connect method works by connecting offset segments using the join-type set through the paths stroke style (round, bevel). Is there an exact definition on how the outline feature should work in this regard ? Is there a way to connect segments by "elongating" them and computing their intersections - this works for straight lines - I'm not sure about bezier curves? About your statement above: "These issues are in the boolean operations code" - can you give some more hints on what is going wrong? I haven't found a reference to the boolean op code in your snippet. Thanks!

NoZ4 commented 4 years ago

I have written code for paper.js for offsetting, please find it here : https://github.com/NoZ4/paper.js-offsets Im not good with javascript or mathamatics and its taken me 6 months to produce this. Its for procedual generation of cad designs for laser cutting

I found offsetting curves and paths are easy, its the self intersections that are the real problem along with floating point errors so in my code I work out where self intersections will occur first and trim curves before offsetting them

Also even if curves dissapper becouse of offsetting the points where curves originally touched must be taken into account I have code creating paths along these points, with arcs.

it works with compound paths, using winding rules, so doughnut shapes can be shrunk/expandid.

I know my code has better accuracy than inkscape, i haven't tested against others.

Im quite cheery that if you expand enough the paths become a circle, or if shrunk turns into a point

it takes into account where paths totally disapper becouse they cant be offset that much and curves/paths inverseing

I got examples on github that show what i mean.

I really hope this can be of use otherwise ive wasted alot of time on nothing

michaeltford commented 4 years ago

Hi, first I wanted to say that I recently started using paper.js and I am amazed. I am porting a tool that renders shapes from Java to Javascript and paper.js is making this very easy. There is one problem that I am am not able to figure out.

I need to be able to render complex paths and find the bounds of these paths. It looks like I can use offset (if it's ready?) but is there a way to render double strokes or other styles? (Similar to below?).

http://www.jhlabs.com/java/java2d/strokes/

My most basic use case is to draw and capture the bounding rect of a double/triple dashed line (Similar to what PowerPoint calls a Compound Line)

https://www.officetohelp.com/powerpoint/how-to-make-compound-line-in-ppt.html

In Java2D these can be done by create a 'Brush' that walks path segments and allows for the ability to render something at each segment. (The work involved is very complicated because of rotations, miter sizes, drawing joins and all the other complicated things that people here understand better than me.

NoZ4 commented 4 years ago

hiya,
with proper working offsets double strokes should be really easy, 5 offsets would be needid. so you have your path which would be the center of your line, you offset it + and - then you have two new lines you just need to cap off, then if you want a double line you offset the original path + or - , just more than you did before and repeat what you did for the original

dashed line should be easy just create gaps in the inital path.

brushing is something we dont have at the moment i think, but shouldnt be too hard to impliment, get even points along a path and just clone whatever you want onto that posistion.

Im currently working on my code, Im not doing double/triple line but am doing lines with variable thickness etc i'll be updating in about a week if thats any use

michaeltford commented 4 years ago

NoZ4. Thank you for the response. I will wait for your updates and then try to build a double/triple stroke using your technique. During my research I didn't find any JavaScript implementations of brushing. (I assume because of off the hidden complexity, google slides has an internal one they use) but paper.js seems to be very close.

I thought I would also add a picture from Powerpoint to show you the effect that I am trying to achieve.

tripple line 2

Looking forward to trying this out!

NoZ4 commented 4 years ago

Hiya everyone

Just thought i would give a update, my code now allows to stroke a path example images : https://github.com/NoZ4/paper.js-offsets/blob/master/VariableWidthstroke.SVG https://github.com/NoZ4/paper.js-offsets/blob/master/Stroke.SVG https://github.com/NoZ4/paper.js-offsets/blob/master/InverseStroke.SVG

theres a few known issues, shown on the page

@lehni do you think it would ever be a idea to add this to the main code? also I used a bit of your code for offsetting single curves

I think this might be a bit quicker than lehni's approach, since i got some escape early functions, but for things like square caps etc I think lehni's approach is much better.

Thanks for all the thumbs up etc before :)

Thanks everyone Noz

northamerican commented 4 years ago

hey, seekers of path offsets. i have yet another option, paper-clipper to share with you. as @lehni wrote above in 2014, the Clipper library handles polygons only. however, it is very accurate in creating offsets for paths without segment handles. this library harnesses Clipper's performant boolean operations (see clipperUnite) as well as its offset functionality. it flattens Paper Paths, offsets them then applies a specialized simplify to restore curves, with good results.

with this external dependency, it isn't viable for inclusion in Paper of course but it's performant and reliable enough for my artistic uses. maybe it will come in use until we have native functionality working and approved.

if you are curious as to how it applies smoothing to the path after offsetting, refer to paper-clipper/paperClipperSimplify.ts. it uses Paper's Path#simplify method on split up pieces of the resulting offset path. this helps retain sharper corners on which simplify overcompensates.