• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
2

[JS] [Action] Split or break a dashed line into separate (real) lines by script

Community Expert ,
Dec 23, 2021 Dec 23, 2021

Copy link to clipboard

Copied

Illustrator does not offer a direct way to convert dashed lines (e.g. for cutting plotters or CNC engraving).

 

Please do not reply to suggest the way to set the outline thickness to a very small value e.g. 0.0001pt. This way still creates filled rectangles and not real lines and is therefore unsuitable.

 

I also know some existing scripts that try to redraw the dash line. Unfortunately, these scripts are not an option either, because the results sometimes differ from the originals.

 

For several years I have used the manual way to break up a dashed line into single (real) lines:
- select the dashed line
- (optionally) create a duplicate and turn off the visibility of the original
- draw a horizontal straight line (helper object)
- remove the dash line attribute from the straight line (helper object)
- create an artbrush from this line (option: Artbrush, no further options, usually just confirm twice)
- delete the line (helper object)
- assign the newly created brush to the original dashed line (or its duplicate)
- use the menu command Object --> Expand Appearance
- ungroup two times
- group the selection and name the group as desired
- delete the artbrush

 

Since this process is rare, but needs to be done over and over again, I wanted to create a script.

Unfortunately there is a problem. Adobe Extendscript cannot be used to create or delete a brush. But it is possible to create a brush with an action. This action can be included in a script. But this way always needs additional confirmations by the user:

- select the option: Artbrush
- confirmation of the selection with [OK]
- confirming the options dialog with [OK] (usually without further settings)

 

 

Question: Does anyone know a way to create an art brush via script or action without additional user interaction (and delete it afterwards)?

 

-------------------------------------------------------------------------------------------

For those interested, here is an example action to create a brush in text form:

 

/version 3
/name [ 16
	63726561746544756d6d794272757368
]
/isOpen 1
/actionCount 1
/action-1 {
	/name [ 16
		63726561746544756d6d794272757368
	]
	/keyIndex 0
	/colorIndex 0
	/isOpen 1
	/eventCount 1
	/event-1 {
		/useRulersIn1stQuadrant 0
		/internalName (ai_plugin_brush)
		/localizedName [ 6
			50696e73656c
		]
		/isOpen 1
		/isOn 1
		/hasDialog 0
		/parameterCount 1
		/parameter-1 {
			/key 1835363957
			/showInPalette -1
			/type (enumerated)
			/name [ 12
				4e657565722050696e73656c
			]
			/value 1
		}
	}
}

 

Many thanks in advance.

 

TOPICS
Draw and design , Scripting

Views

3.7K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
Guide ,
Jan 23, 2022 Jan 23, 2022

Copy link to clipboard

Copied

Cool!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 23, 2022 Jan 23, 2022

Copy link to clipboard

Copied

A very good approach, sttk3.

 

Unfortunately, depending on the specific dashed line settings, it often changes the original appearance to a considerable degree.

 

But I'm sure it may be improved.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 23, 2022 Jan 23, 2022

Copy link to clipboard

Copied

I apologize for any inconvenience this may cause.
Unfortunately, I don't have time to give my topic the attention it deserves at the moment.

 

However, I thank you very much for all the solutions posted so far. Unfortunately, I have not yet been able to test the last two promising variants of @Kurt Gold  and @CarlosCanto  extensively.

 

A first test with @sttk3  very good script showed very good results with newly created stroke lines (much more precise than with an artbrush with deviations of less than 0.05 mm). However, the script does not cope well with rounded caps. There are indeed deviations there. At this point I unfortunately had to interrupt my tests. And thanks also to you for this great solution.

 

I will definitely not forget this topic. When I have enough time again, I will test all suggestions in detail and give accurate feedback.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 23, 2022 Jan 23, 2022

Copy link to clipboard

Copied

Pixxxelschubser,

 

my guess is that you are just overwhelmed by all the half-baked approaches so far. You may possibly consider to never use dashed paths again. 🙂

 

But I think one day someone will crack the nut. I have some other ideas, but currently they do not work as they are supposed to work.

 

I'm curious about Mark's (m1b) approach.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 23, 2022 Jan 23, 2022

Copy link to clipboard

Copied

pixxxelschubser_0-1642976040320.png

 

… I'm curious about Mark's (m1b) approach.


By @Kurt Gold

 

Yes, me too.

😉

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 23, 2022 Jan 23, 2022

Copy link to clipboard

Copied

Improved the appearance of rounded caps and projecting caps.

/**
  * @File expand a dashed stroke  
  * https://community.adobe.com/t5/illustrator-discussions/js-action-split-or-break-a-dashed-line-into-separate-real-lines-by-script/td-p/12614309
  * @version 1.0.1
  * @author sttk3.com
  * @copyright © 2022 sttk3.com
*/

//@target 'illustrator'

(function() {
  if(app.documents.length <= 0) {return ;}
  var doc = app.documents[0] ;

  // only one selection is allowed
  var sel = doc.selection ;
  var messageInvalidSelection = 'Select one dashed stroke and execute this script.' ;
  if(sel.length != 1) {
    alert(messageInvalidSelection) ;
    return ;
  }
  
  // terminate when selected item is not a path, not a dashed stroke, or has a fill
  var originalPath = sel[0] ;
  if(!/^PathItem$/.test(originalPath.constructor.name)) {
    alert(messageInvalidSelection) ;
    return ;
  }
  if(originalPath.strokeDashes.length <= 0) {
    alert(messageInvalidSelection) ;
    return ;
  }
  if(originalPath.filled) {
    alert('This script should be execute after the fill is removed.') ;
    return ;
  }

  // generate a unique color
  var tempSpot = doc.spots.add() ;
  var tempColor = new SpotColor() ;
  tempColor.spot = tempSpot ;
  tempColor.tint = 100 ;

  try {
    var pathfinderGroup = originalPath.layer.groupItems.add() ;
    pathfinderGroup.move(originalPath, ElementPlacement.PLACEBEFORE) ;
    var maskWidth = originalPath.strokeWidth + 1 ;

    // object to fill dash
    var dashPath = originalPath.duplicate(pathfinderGroup, ElementPlacement.PLACEATEND) ;
    dashPath.strokeWidth = maskWidth ;
    dashPath.strokeCap = StrokeCap.BUTTENDCAP ; // make the dash length unchangeable

    // object to fill gap
    var gapPath = originalPath.duplicate(pathfinderGroup, ElementPlacement.PLACEATEND) ;
    gapPath.strokeDashes = [] ;
    gapPath.strokeColor = tempColor ;

    // leave fill only at gaps
    doc.selection = [pathfinderGroup] ;
    app.executeMenuCommand('OffsetPath v22') ; // Outline Stroke
    app.executeMenuCommand('Live Pathfinder Subtract') ;
    app.executeMenuCommand('expandStyle') ; // Expand Appearance
    app.executeMenuCommand('compoundPath') ; // Compound Path Make
    
    // remove gaps of originalPath by live paint
    originalPath.strokeDashes = [] ;
    originalPath.selected = true ;
    app.executeMenuCommand('Make Planet X') ; //  Live Paint Make
    app.executeMenuCommand('Expand Planet X') ; //  Live Paint Expand
    app.executeMenuCommand('ungroup') ;
    app.redraw() ;
    
    // remove gapPath
    var tempGroups = doc.selection ;
    var itemColor ;
    for(var i = tempGroups.length - 1 ; i >= 0 ; i--) {
      itemColor = tempGroups[i].pathItems[0].fillColor ;
      if((itemColor.constructor.name == 'SpotColor') && (itemColor.spot == tempSpot)) {
        tempGroups[i].remove() ;
        break ;
      }
    }
  } catch(e) {
    alert(e) ;
  } finally {
    tempSpot.remove() ;
  }
})() ;

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 24, 2022 Jan 24, 2022

Copy link to clipboard

Copied

Your second version is a very good improvement, sttk3.

 

The next level would be to find a way to allow multiple selected dashed paths with different stroke attributes. I have an action that can almost do it, but currently it is still not precise enough and it will alter the dash positions a bit.

 

It's a challenging game.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 24, 2022 Jan 24, 2022

Copy link to clipboard

Copied

Here's my offering to solve this problem—I call it Dasher. This one really sent me down the rabbit hole. 🙂

 

After some failed starts that only got 95% of the way, I decided to meet the problem head-on, and try to solve each little component of the task and put them all together. I'm very happy with it so far and I think it meets all your criteria @pixxxelschubser.

 

For my convenience I've written the script in 3 files:

1. Convert Dashed Stroke.js — this is an example implementation. Just run this script to test it out.

2. Bez.js — handles the path stuff and bezier maths (thanks so much to Hiroyuki Sato's Divide (Length).jsx)

3. Dasher.js — handles dash pattern generation.

Keep them in the same folder when you are testing as they include each other.

 

Rather than posting long confusing scripts here, I've created a public github page for the project—check out the Read Me file there. You can also download the scripts directly.

 

To test it, just run the "Convert Dashed Stroke.js" script on a selection in Illustrator.

 

Needs testing! There are some complexities involved in mimicking Illustrator's algorithms and I am *positive* the script will fail in various edge cases that I haven't thought of, so any bugs and feedback would be awesome. Feel free to post issues to github or just let me know via the forum here.

- Mark

 

quick-demo-anim.gif

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 25, 2022 Jan 25, 2022

Copy link to clipboard

Copied

Excellent approach, Mark. Visiting the rabbit hole was a good idea.

 

One thing I noticed is that your script is obviously referring to the stroke weight of the topmost selected object and applies this stroke weight to all other objects, even if they have different stroke weights. I'm not sure if this is intended.

 

I also noticed that the script may get pretty unstable if the selection includes many objects with different attributes. But it is really a very good approach.

 

Just for fun and to show that it can be done with actions, I'd like to provide Dash Nipper version 4. It does not need any helper objects and should work in almost all cases. A bit bumpy, just as any action is bumpy by nature.

 

You can download it here:

 

Dash Nipper 4

 

The .zip file contains a sample Illustrator file (dash_sample_4.ai) and an action set file (dash_nipper_4.aia).

 

Instruction:

 

- Unzip the file
- Open dash_sample_4.ai
- In the Actions palette import the action set dash_nipper_4.aia
- Select all and run the action

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 25, 2022 Jan 25, 2022

Copy link to clipboard

Copied


One thing I noticed is that your script is obviously referring to the stroke weight of the topmost selected object and applies this stroke weight to all other objects, even if they have different stroke weights. I'm not sure if this intended.

 

I'll have to look into this one further as I haven't been able to reproduce it. When I do a simple test with 3 items, each with differing strokeWidths, the script converts them and applies the correct strokeWidth.

 

I also noticed that the script may get pretty unstable if the selection includes many objects with different attributes.

 

 

I can easily see this breaking, but to save me time, do you have a handy sample file that breaks it? I haven't got time at the moment to look at it again, but I'll try and improve those shortcomings.

 

As always I'm intrigued by your wizardry with actions and I'll definitely check out Dash Nipper 4 when I get back to it.

 

Thanks for looking.

- Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 25, 2022 Jan 25, 2022

Copy link to clipboard

Copied

Hi Kurt, I tried out Dash Nipper 4 (MacOS) and whoah... it's incredible! I still can't believe the magic you manage to achieve with actions. When I have more time I will set myself the task of trying to understand how it works.

- Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 25, 2022 Jan 25, 2022

Copy link to clipboard

Copied

Hi Mark,

 

you can reproduce both issues if you take the sample .ai file I provided in my previous post (Dash Nipper 4). Open dash_sample_4.ai, select all dashed objects and execute your script.

 

As for the unstable part my guess is that, maybe intentionally or not, there is some kind of limit that controls how many single objects can be created with the script.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 25, 2022 Jan 25, 2022

Copy link to clipboard

Copied

Thanks Kurt, you're right about both bugs. It turns out that both are due to my absentmindedness! Ha ha.

 

1. The strokeWidth issue was simply that I didn't implement it at all! The only reason it sort of worked was due to the current stroke being applied automatically by Illustrator. I've made it explicit now.

 

2. The other issue was due to me leaving in some safety net code while my looping was a bit flaky during development. It deliberately throws an error if one of the loops goes past 100 cycles, must have triggered on your long paths. I've commented them out now.

 

I have updated on github, so feel free to download again.

- Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 26, 2022 Jan 26, 2022

Copy link to clipboard

Copied

Mark,

 

I tried your modified version. It works pretty well now and if you ask me, I'd say you are the well-deserved winner of this fascinating contest.

 

One essential advantage of your script is that it properly produces separate groups out of each dashed path, whereas Dash Nipper 4 currently makes just one giant group.

 

One thing I noticed however is that the script may take a lot of time to execute the conversion if the selection contains a great number of paths. For example, if you run the script with a selection that finally produces about 4000 single dashes with about 8000 points, it may take about 15 minutes or even longer to complete the conversion. The action is about 50 times faster in that case.

 

So, at the beginning of your script you may consider to check if the selection includes a huge number of objects and if so provide an alert that informs about the possible very long execution time.

 

Again, your script is an excellent approach, Mark.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 26, 2022 Jan 26, 2022

Copy link to clipboard

Copied

Thanks again for testing @Kurt Gold . Yeah I haven't given a thought to performance—it's a weak area for me. I'd love if any Illustrator scripters reading this had any ideas for improving performance. There should be some low-hanging fruit—I literally haven't made any performance tweaks. For now I'm happy if it works!

 

Meanwhile @sttk3 has another very good scripting approach that seems excellent. Has been a fascinating question, @pixxxelschubser. You can have some fun with these when you get back. 🙂

- Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 26, 2022 Jan 26, 2022

Copy link to clipboard

Copied

expandDashedStroke.jsx 1.1.0

 

Improve: 
Allow multiple selection
Support for dotted strokes
Localized alerts into English and Japanese

 

https://gist.github.com/sttk3/a087df0d76198e9fe3d5c1c8e76691be 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 26, 2022 Jan 26, 2022

Copy link to clipboard

Copied

Nice one, @sttk3 seems to work really well. 🙂

- Mark

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 27, 2022 Jan 27, 2022

Copy link to clipboard

Copied

Excellent improvements, sttk3 !

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 31, 2022 Jan 31, 2022

Copy link to clipboard

Copied

sttk3,

 

I did some more experiments and my conclusion is that you provided the most advanced approach so far.

 

I'm curious about pixxxelschubser's feedback.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 31, 2022 Jan 31, 2022

Copy link to clipboard

Copied

quote

 

… I'm curious about pixxxelschubser's feedback.

 


By @Kurt Gold

 

Me too.

😉

Probably in two to three weeks I can again extensively deal with your great solutions.

(It is now 1 o'clock in the morning.) I say now once again thank you to all and good night.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 01, 2022 Feb 01, 2022

Copy link to clipboard

Copied

Converting a dashed path to perfectly accurate individual line segments should not be too hard to script:

 

1. Duplicate the dashed path, and turn off the duplicate’s stroke.

2. Outline the dashed path’s stroke. This gives you filled ‘rectangular’ boxes. (If the dashes use rounded caps, turn those off first.)

3. Select both 1 & 2 and apply Pathfinder Divide.

4. Delete the unstroked path that’s left over.

5. Iterate over each point in each path item, collecting their coordinates in a hash table (pseudocode):

 

discard = {}
keep = []
for pathItem in pathItems:
  for point in pathItem.points:
    key = point.x+','+point.y
    if key in discard:
      keep.push(point)
    else:
      discard[key] = pointObject

for pointObject in table.values:
  pointObject.delete()

for point in keep:
   point.parent.stroke = originalStrokeWidth

 

Simple algorithm: it’s looking for all occurrences of two overlapping points, i.e. the points at which each box was sliced down the middle by the original path. One of those points it keeps and the other it later discards along with all non-overlapping points. Apply a solid, not dashed, stroke to the remaining paths, and you should be golden.

 

AI’s ExtendScript doesn’t have commands for outlining and expanding strokes, so you’ll have to select the paths and use:

 

app.executeMenuCommand("Live Outline Stroke")
app.executeMenuCommand("expandStyle")

 

and:

 

app.executeMenuCommand("Live Pathfinder Divide")
app.executeMenuCommand("expandStyle")

 

 Touch-wood, everything works as described above (althought never underestimate the AI APIs’ ability to screw your day up for the lulz).

 

Normally I’d offer to send you a finished, tested, working script and bill you a day’s work. Today, I am in a benevolent mood and also completely slammed, so there you go—some self-assembly required. Assuming noone else thought of it first, if/when you get it working, pop $100 to msf.org as a charitable donation and we’ll call it square. Good luck.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 01, 2022 Feb 01, 2022

Copy link to clipboard

Copied

Well, hhas01, that's another good way, but we have a more demanding coffee party here.

 

I think it is rather obvious that one important part of the task discussed in this thread is to preserve all appearance attributes of the original dashed or dotted paths (stroke weights, caps, colours). If that was not required, you could just use one of my earlier Dash Nipper actions, for example.

 

Hopefully, I did not overlook something, but as far as I can see your approach will not retain the original appearance attributes.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 01, 2022 Feb 01, 2022

Copy link to clipboard

Copied

My approach is not so dissimilar to sttk3’s, except mine doesn’t care about knocking out the gaps: it is purely concerned with slicing the original continuous path into segments at the exact points where each visible dash begins and ends, then deleting all the gunk until only a single set of “dash paths” remain. OP made it clear these new paths must not deviate from the original dashes’ start/end/curvature in any way, so that’s the not-so-obvious bit I focused on solving. (This is not my first slice-n-dice rodeo. Took me 2mins to see the solution; far longer to write these posts!)

 

Since AI’s Outline Path and Pathfinder Subtract like to remove the original stroke attributes, OP might want to get the stroke color, width, caps, etc. values (but not dash properties as you want the new line solid) from the original path at the beginning and apply those values to the new paths at the end. Which is trivial to do [1] and any JSX scripter will know how to do it, so I didn’t detail it beyond those last 2 lines of pseudocode.

 

As I say, normally I’d just write the finished script, cost that work, and offer it straight to OP, but I’m already full with client work.  Speaking of which, I must get back. So adieu, and JSX folks here are welcome to try my solution and see how it compares to the rest.

 

(BTW, OP really needs to post Before and After examples showing how they want the artwork constructed at the vector level. That would help everyone here a lot.)

 

--

[1] Unless you’re talking about styles applied in the Appearances panel then, yes, you’re SOOL as none of that stuff is scriptable and it stomps all over the style properties that are. But if OP wants plain unadorned vector paths for a pen plotter/laser cutter to precisely follow, with perhaps a hairline stroke so humans can still see them, I’m not sure why they’d want to reapply AI brushes and other fancy visual stuff.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 01, 2022 Feb 01, 2022

Copy link to clipboard

Copied

Oh, that sounds as if you took offence due to my comment, hhas01.

 

Please be assured that no offence was intended. I'm sure that your elaborated approach will or would be brilliant.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 01, 2022 Feb 01, 2022

Copy link to clipboard

Copied

No offence taken. Just my normal brusque self.

 

(I am a little annoyed at myself for spending far too long posting—I could’ve just about written the script! Alas, shiny distractions are…SQUIRREL!)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines