Copy link to clipboard
Copied
Hello! Adobe Illustrator CS 6
I have script, wich groups filled paths by colors. Link to script and traced image. Traced_image.rar - Google Drive
I have traced image, it has 25 colors. The script creates 25 groups, paths of each color in each group.
I need to modify script, i want to insert text number in visible middle of the each filled path. So one group is one number. From 1 to 25.
Can anyone help me?
Hello all, here comes the final version.
This time "offset path effect" been used. I thought this is a possible way at beginning, but never give it a try, until today.
It deal with both Path and Compound Path. Test the sample document, it only took 31 seconds.
Copy link to clipboard
Copied
take a look at this thread.
it's not a simple task to get the gravitational center of an irregular object.
I'm sure its possible with some wiz bang algorithm.
but I am not going to try to tackle that with my math skills
if you need a hand modifying it for your needs let me know.
Copy link to clipboard
Copied
Thank you, but my skill is not enouth to modify and compute your script with this one. Can you take a look on algoritm? The problem is that script generating sub and sub layers, so your script can work with 1 level layers only.
Look please on script:
#target illustrator
if (app.documents.length > 0)
{
if (app.activeDocument.pageItems.length > 0)
{
var release_to_layers_window; // make window global
var doc = app.activeDocument;
var doc_artboard = doc.artboards[0].artboardRect;
var unlocked_layers_count = 0; // number of unlocked layers in layer palette for progress bar
var msis_message_1 = "\nThis script will place each object within this current document into a new layer based on it's fill color. "+
"As the script currently does not detect locked layers and locked objects you need to unlock your layers and objects before you can run this script. " +
"Note that running this script will modify your document. You might want to save your document first.";
var doc = app.activeDocument;
var Counter = app.activeDocument.pageItems.length;
var LayerName = "";
var ReleaseMethod = 1;
// start dialog window
release_to_layers_dialog();
}
// what if no document of no objects?
if (app.documents.length < 1)
{alert("No open documents found. Please open a document before you run this script");}
if (app.documents.length > 0 && app.activeDocument.pathItems.length < 1)
{alert("No objects found in this documents. Please add some objects before you run this script");}
}
// ********************************************************************************************************
// ** **
// ** find the most common value in an array **
// ** **
// ** http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Q_20871554.html **
// ** var myArray = ["apple","banana","orange","banana","tomato","grape","apple"]; **
// ** alert( GetMostCommonColor(myArray) ); **
// ** **
// ********************************************************************************************************
function GetMostCommonColor(theArray)
{
var tempArray = new Array();
tempArray.length = 0;
tempArray = theArray.slice(0,theArray.length);
tempArray.sort();
tempArray[tempArray.length] = "";
mVal = aVal = "";
mCnt = aCnt = 0;
for(r=0;r<tempArray.length;r++)
{
if(aVal!=tempArray
) {
if(aCnt>mCnt)
{
mCnt = aCnt;
mVal = aVal
}
aVal = tempArray
; aCnt = 1;
} else
{
aCnt++;
}
}
// return [mVal, mCnt]; // returns value and count
return mVal; // only returns value
}
// ********************************************************************************************************
// ** **
// ** create a layer name for the current object **
// ** **
// ********************************************************************************************************
function ConstructLayerNameBasedOnFillColor(myCurrentObject)
{
var myLayerName = "Unknown";
if (myCurrentObject.typename == "TextFrame") { myLayerName = "Text Objects"; }
if (myCurrentObject.typename == "SymbolItem") { myLayerName = "Symbols"; }
if (myCurrentObject.typename == "RasterItem") { myLayerName = "Raster Objects"; }
if (myCurrentObject.typename == "PathItem")
{
if ( myCurrentObject.filled == true )
{
myLayerName = 'Object with unknown Fill Color'; // default name for if no color can be detected
if (myCurrentObject.fillColor == "[CMYKColor]") // CMYK color Item
{
myLayerName = "CMYK: " + Math.round(myCurrentObject.fillColor.cyan) + "," + Math.round(myCurrentObject.fillColor.magenta) + "," + Math.round(myCurrentObject.fillColor.yellow) + "," + Math.round(myCurrentObject.fillColor.black);
}
if (myCurrentObject.fillColor == "[RGBColor]") // RGB color Item
{
myLayerName = "RGB: " + Math.round(myCurrentObject.fillColor.red) + "," + Math.round(myCurrentObject.fillColor.green) + "," + Math.round(myCurrentObject.fillColor.blue);
}
if (myCurrentObject.fillColor == "[GrayColor]") // Gray color Item
{
myLayerName = "Gray: " + Math.round(myCurrentObject.fillColor.gray);
}
if (myCurrentObject.fillColor == "[LabColor]") // LabColor color Item
{
myLayerName = "Lab: " + Math.round(myCurrentObject.fillColor.a) + "," + Math.round(myCurrentObject.fillColor.b) + "," + Math.round(myCurrentObject.fillColor.i);
}
if (myCurrentObject.fillColor == "[GradientColor]") // Gradient color Item
{
myLayerName = "Gradient Fill";
}
if (myCurrentObject.fillColor == "[NoColor]") // No Color Item
{
myLayerName = "No Color";
}
if (myCurrentObject.fillColor == "[PatternColor]") // Pattern Color Item
{
myLayerName = "Pattern Fill";
}
if (myCurrentObject.fillColor == "[SpotColor]") // Spot Color Item
{
// cmyk spot
if (myCurrentObject.fillColor.spot.spotKind == SpotColorKind.SPOTCMYK) // CMYK color Item
{
myLayerName = "Spot CMYK: " + Math.round(myCurrentObject.fillColor.spot.color.cyan) + "," + Math.round(myCurrentObject.fillColor.spot.color.magenta) + "," + Math.round(myCurrentObject.fillColor.spot.color.yellow) + "," + Math.round(myCurrentObject.fillColor.spot.color.black);
}
// rgb spot
if (myCurrentObject.fillColor.spot.spotKind == SpotColorKind.SPOTRGB) // RGB color Item
{
myLayerName = "Spot RGB: " + Math.round(myCurrentObject.fillColor.spot.color.red) + "," + Math.round(myCurrentObject.fillColor.spot.color.green) + "," + Math.round(myCurrentObject.fillColor.spot.color.blue);
}
// lab spot
if (myCurrentObject.fillColor.spot.spotKind == SpotColorKind.SPOTLAB) // RGB color Item
{
myLayerName = "Spot Lab: " + Math.round(myCurrentObject.fillColor.spot.color.a) + "," + Math.round(myCurrentObject.fillColor.spot.color.b) + "," + Math.round(myCurrentObject.fillColor.spot.color.i);
}
}
}
else
{
myLayerName = "Transparant Fill";
}
}
if (myLayerName == undefined) {myLayerName = "Temporary Layer";}
if (myLayerName == "") {myLayerName = "Temporary Layer";}
if (myLayerName.length==0) {myLayerName = "Temporary Layer";}
try
{
doc.layers.getByName(myLayerName);
}
catch (e)
{
doc.layers.add().name = myLayerName;
}
return myLayerName;
}
// ********************************************************************************************************
// ** **
// ** ungroup objects on current layer **
// ** **
// ********************************************************************************************************
function Ungroup(WhereToUngroup, aGroup) // where to ungroup? layer, document, other group?
{
try
{
for (s=aGroup.pageItems.length-1; s>=0; s--)
{
WhereToUngroup = CreateLayerNameFill(myCurrentObject); // ????????? should be something like WhereToUngroup = CreateLayerNameFill(=aGroup.pageItems); // ???????????????????????????
aGroup.pageItems
.move(WhereToUngroup, ElementPlacement.PLACEATBEGINNING);}
}
catch(err)
{
}
}
// ********************************************************************************************************
// ** **
// ** remove layerswith no objects **
// ** **
// ********************************************************************************************************
function RemoveEmptyLayers()
{
var ThisDoc = app.activeDocument;
var ActiveLayer = '';
for (t = ThisDoc.layers.length-1; t>=0; t--)
{
ActiveLayer = ThisDoc.layers
; if (ActiveLayer.pageItems.length == 0)
{
try
{
ActiveLayer.remove();
}
catch(err)
{
}
}
}
}
// ********************************************************************************************************
// ** **
// ** building and showing main dialog **
// ** **
// ********************************************************************************************************
function release_to_layers_dialog() {
// Export dialog
release_to_layers_window = new Window('dialog', 'Release objects to layers based on object fill color');
// PANEL with usage instructions
release_to_layers_window.MessagePanel = release_to_layers_window.add('panel', undefined, 'Release Objects to Layers');
// GROUP
var Message_Group = release_to_layers_window.MessagePanel.add('group', undefined, '')
Message_Group.orientation = 'column';
Message_Group.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]
// Labels
var Message_Group_label_1 = Message_Group.add('statictext', undefined, msis_message_1, {multiline:true});
Message_Group_label_1.size = [500,80];
// PANEL with group and compound path handling
release_to_layers_window.OptionsPanel = release_to_layers_window.add ('panel', undefined, 'Group and Compound Path Items:');
// GROUP
var Radio_Group = release_to_layers_window.OptionsPanel.add('group', undefined, '')
Radio_Group.alignChildren = "left";
Radio_Group.size = [500,65];
Radio_Group.orientation = 'column';
// Radio Boxes
var RadioBox1 = Radio_Group.add ("radiobutton", undefined, "Do not process Group and Compound Path Items.");
var RadioBox2 = Radio_Group.add ("radiobutton", undefined, "Release Groups and Compound Path Items by most common color.");
var RadioBox3 = Radio_Group.add ("radiobutton", undefined, "Ungroup Group and Compound Path Items (caution: might alter shape appearance).");
RadioBox2.value = true;
// PANEL with Progressbar
release_to_layers_window.ProgressPanel = release_to_layers_window.add('panel', undefined, 'Status:');
// GROUP
var Progress_Group = release_to_layers_window.ProgressPanel.add('group', undefined, '')
Progress_Group.orientation = 'column';
Progress_Group.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]
Progress_Group.size = [500,5];
// progressbar
release_to_layers_window.ProgressProgressBar = release_to_layers_window.ProgressPanel.add( 'progressbar', undefined, 0, 100 );
release_to_layers_window.ProgressProgressBar.size = [480,10];
// label
release_to_layers_window.ProgressLabel = release_to_layers_window.ProgressPanel.add('statictext', undefined, 'Found ' + Counter + ' objects in this document.' );
release_to_layers_window.ProgressLabel.size = [ 480,20 ];
// Buttons don't have a PANEL
// GROUP
Button_Group = release_to_layers_window.add('group', undefined, '');
Button_Group.orientation = 'row'
Button_Group.cancelBtn = Button_Group.add('button', undefined, 'Cancel', {name:'cancel'});
Button_Group.cancelBtn.onClick = function() { msis_ai_dlg.close() };
Button_Group.okBtn = Button_Group.add('button', undefined, 'Release', {name:'ok'});
Button_Group.okBtn.onClick = function()
{ Button_Group.okBtn.enabled = false;
Button_Group.cancelBtn.enabled = false;
RadioBox1.enabled = false;
RadioBox2.enabled = false;
RadioBox3.enabled = false;
if (RadioBox1.value == true) {ReleaseMethod = 1;}
if (RadioBox2.value == true) {ReleaseMethod = 2;}
if (RadioBox3.value == true) {ReleaseMethod = 3;}
Process_Objects();
};
release_to_layers_window.show();
}
//var textRef1 = myCurrentObject.textFrames.add();
//textRef1.contents = "1";
// ********************************************************************************************************
// ** **
// ** execute main routine when clicking the Release button **
// ** **
// ********************************************************************************************************
function Process_Objects()
{
// Release to layers but skip Groups and Compound Paths Items OR move groups and compound paths but keep then as group objects
if (ReleaseMethod == 1 || ReleaseMethod == 2)
{
for ( i=0; i < Counter; i++ ) //123
{
LayerName = "0";
try
{
CurrentItem = doc.pageItems;
if (CurrentItem.typename != "GroupItem" && CurrentItem.typename != "CompoundPathItem" && CurrentItem.parent.typename != "GroupItem" && CurrentItem.parent.typename != "CompoundPathItem") // no need to create layers for objects within grouped items
{
LayerName = ConstructLayerNameBasedOnFillColor(CurrentItem);
CurrentItem.move( app.activeDocument.layers.getByName( LayerName ), ElementPlacement.PLACEATBEGINNING );
}
} // try
catch(err)
{ // except
alert("An error occured processing objects.\n(" + err + ").\n\nFunction: Process_Objects / method=1.");
} // except
release_to_layers_window.ProgressLabel.text = 'Processed ' + i + ' objects out of ' + Counter + ' objects in total.';
release_to_layers_window.ProgressProgressBar.value = (100 / Counter) * i;
release_to_layers_window.update();
} // for
} // end method 1
// Release to layers, move Group and Compound Path Items based on most common fill color
if (ReleaseMethod == 2)
{
// first move all group objects
LayerName = "0";
for ( j=0; j < doc.groupItems.length; j++ )
{
var CurrentGroupItem = doc.groupItems
; var MyArray = new Array;
var TempLayerName = "";
for (m = CurrentGroupItem.pageItems.length-1; m>=0; m--)
{
TempLayerName = ConstructLayerNameBasedOnFillColor( CurrentGroupItem.pageItems
); MyArray.push( TempLayerName );
}
LayerName = GetMostCommonColor(MyArray);
CurrentGroupItem.moveToBeginning(app.activeDocument.layers.getByName( LayerName ) );
release_to_layers_window.ProgressLabel.text = 'Processed ' + j + ' group objects out of ' + Counter + ' objects in total.';
release_to_layers_window.ProgressProgressBar.value = (100 / Counter) * j;
release_to_layers_window.update();
}
// next move all compound path objects
LayerName = "0";
for ( j=0; j < doc.compoundPathItems.length; j++ )
{
var CurrentCompoundItem = doc.compoundPathItems
; var MyArray = new Array;
var TempLayerName = "";
for (m = CurrentCompoundItem.pathItems.length-1; m>=0; m--)
{
TempLayerName = ConstructLayerNameBasedOnFillColor( CurrentCompoundItem.pathItems
); MyArray.push( TempLayerName );
}
LayerName = GetMostCommonColor(MyArray);
CurrentCompoundItem.moveToBeginning(app.activeDocument.layers.getByName( LayerName ) );
release_to_layers_window.ProgressLabel.text = 'Processed ' + j + ' group objects out of ' + Counter + ' objects in total.';
release_to_layers_window.ProgressProgressBar.value = (100 / Counter) * j;
release_to_layers_window.update();
}
}
// Release to layers and ungroup Group and Compound Path Items
if (ReleaseMethod == 3)
{
for ( k=0; k < Counter; k++ ) //123
{
LayerName = "0";
try
{
CurrentItem = doc.pageItems
; LayerName = ConstructLayerNameBasedOnFillColor(CurrentItem);
if (CurrentItem.typename != "GroupItem" && CurrentItem.typename != "CompoundPathItem") // no need to create layers for objects within grouped items
{
CurrentItem.move( app.activeDocument.layers.getByName( LayerName ), ElementPlacement.PLACEATBEGINNING );
} // try
else
{
UnGroupLayer = app.activeDocument.layers.getByName( LayerName );
Ungroup( UnGroupLayer , CurrentItem );
}
}
catch(err)
{ // except
alert("An error occured processing objects.\n(" + err + ").\n\nFunction: Process_Objects / method=3.");
} // except
release_to_layers_window.ProgressLabel.text = 'Processed ' + k + ' objects out of ' + Counter + ' objects in total.';
release_to_layers_window.ProgressProgressBar.value = (100 / Counter) * k;
release_to_layers_window.update();
} // for
} // end methode 3
RemoveEmptyLayers();
release_to_layers_dialog.close();
}
Copy link to clipboard
Copied
I'm not sure you will be happy with the outcome of this.
I can tack the 2 scripts together, but the method used for finding the center of an item is clunky and slow.
I am running a test now, and the script has been running for over 10 min already, I'll see how long it takes, if it even finishes...
Did you number the sample file by hand?
Copy link to clipboard
Copied
It ran for an hour. before I quit it.
This is not a viable solution for this unless it can be made less clunky.
we could add the numbers for each item via a script.
but they would just be centered to the object, and not gravitationaly centered.
it would then be a manual process to move the numbers to a visually nice location.
I'll have another think about it and let you know if I can work something out...
Copy link to clipboard
Copied
Copy link to clipboard
Copied
this could be a good idea silly,
I still worry about how long this will take to run it 500 or 1000 times.
I'll have a play. not sure I'll have much luck getting a good understanding of that code to be able to trim it down.
Copy link to clipboard
Copied
Yes, my own math skills are less than what's needed to understand the circle-fill algorithm. But, with that algorithm alone, it is a gateway to do many 2-D manipulation techniques!
Copy link to clipboard
Copied
I think I have a better way of doing this.
involving adding strokes and expanding...
I won't go in to the details now, but should be WAY more efficient then creating and destroying an action many times per object...
not as fast as pure math would be but better.
I'll post back when I have a working example
Copy link to clipboard
Copied
I found a function to find shape centroids
var idoc = app.activeDocument;
var ipath = idoc.selection[0];
var pps = ipath.pathPoints;
var pts = [];
for (var a=0; a<pps.length; a++) {
var pp = pps.anchor;
pts.push({x:pp[0], y:pp[1]});
}
//$.writeln(pts.toSource());
var c = get_polygon_centroid (pts);
//$.writeln(c.toSource());
var pt = idoc.pathItems.add();
pt.setEntirePath([[c.x, c.y], [c.x, c.y]]);
pt.stroked = true;
pt.filled = false;
pt.strokeCap = StrokeCap.ROUNDENDCAP;
pt.strokeWidth = 5;
// function by Myobis
function get_polygon_centroid(pts) {
var first = pts[0], last = pts[pts.length-1];
if (first.x != last.x || first.y != last.y) pts.push(first);
var twicearea=0,
x=0, y=0,
nPts = pts.length,
p1, p2, f;
for ( var i=0, j=nPts-1 ; i<nPts ; j=i++ ) {
p1 = pts; p2 = pts
; f = p1.x*p2.y - p2.x*p1.y;
twicearea += f;
x += ( p1.x + p2.x ) * f;
y += ( p1.y + p2.y ) * f;
}
f = twicearea * 3;
return { x:x/f, y:y/f };
}
Copy link to clipboard
Copied
Nice looking script, but not sure its doing the correct thing.
in this image the black dot is produced by this script.
the blue scribble is where I would expect the point to land.
Copy link to clipboard
Copied
here is the working example I came up with.
it runs too slow but is way more reliable then the create action method.
I added a timer so you can see the run time.
on my sample file (12 shapes) it took 5 - 10 seconds to run.
THIS WILL RUN SLOW!!!
function add_nums(){
// fiddle with these values to adjust speed vs accuracy
var percentage = 1; // take average betwenn hight and width and multiplies it by this to get starting stroke weight - 1 = 100%
var increment = .8; // amount to add to percentage on each iteration
var doc = app.activeDocument;
var lays = doc.layers;
var layNames = [];
for(var i=0; i<lays.length; i++){
layNames.push(lays.name);
}
// new layers
var WORK_LAY = doc.layers.add();
WORK_LAY.name = "Working Layer";
var NUM_LAY = doc.layers.add();
NUM_LAY.name = "Numbers";
// main working loop
for(var i=0; i<layNames.length; i++){
//process each layer
var lay = lays.getByName(layNames);
lay.name = lay.name + " Num:" + (i+1);
for(var j=0; j<lay.pathItems.length; j++){
// process each pathItem
var pth = lay.pathItems
; var per = percentage; // reset the path percentage for each shape
var cent = [];
var Count = 0;
if(FatPart(pth) === "error"){
alert("Loop Error, try resetting\npercentage to 1,\nand\nincroment to .8\nin the script file");
return;
}
// Create the text frame
var txt = NUM_LAY.textFrames.add();
txt.contents = i+1;
txt.textRange.justification = Justification.CENTER;
txt.position = [cent[0]-txt.width/2,cent[1]+txt.height/2];
pth.filled = false;
pth.stroked = true;
}
}
//clean up
WORK_LAY.remove();
// find fat section of a shape
function FatPart(pth){
var success = false;
while(!success){
success = process();
// if recursive function runs too many times give option to exit
Count++;
if(Count%100 === 0){
var keepGoing = confirm("Process function has run " + Count + " times on current object.\nWould you like to continue trying?");
if(!keepGoing){
return "error";
}
}
}
function process(){
// make sure we start with nothing selected
doc.selection = null;
// make a copy of the shape to work on
var item = pth.duplicate(WORK_LAY,ElementPlacement.PLACEATBEGINNING);
item.filled = false;
item.stroked = true;
// scale works out how thick the stroke shold be
var scale = ((item.height+item.width)/20)*per;
item.strokeWidth = scale;
// select the items and outline the stroke
item.selected = true;
app.executeMenuCommand ('OffsetPath v22');// = Outline Stroke
var sel = doc.selection;
if(sel[0].typename === "CompoundPathItem"){
if(sel[0].pathItems.length>2){
// too many paths, increase stroke and retry
sel[0].remove()
per = per + increment;
return false;
}else{
// Remove the larger of the 2 shapes in the compoundPath
if(Math.abs(sel[0].pathItems[0].area)>Math.abs(sel[0].pathItems[1].area)){
sel[0].pathItems[0].remove();
}else{
sel[0].pathItems[1].remove();
}
// compare size against original - Aiming for under 10%
if(Math.abs(sel[0].pathItems[0].area)>Math.abs(item.area)/10){ // the 10 is ten percent of original size
sel[0].pathItems[0].remove();
per = per + increment;
return false;
}else{
// now we should have correct size to center text to
// return X,Y of shapes Center
var B = sel[0].geometricBounds;
cent.push(B[0]+(B[2]-B[0])/2);
cent.push(B[1]+(B[3]-B[1])/2);
sel[0].remove()
return true;
}
}
}else{
// shape filled completely, reduced stroke and retry
sel[0].remove()
per = per - increment/10;
return false;
}
}
}
}
var timer = Date.now();
add_nums();
var x = (Date.now()-timer);
alert('conversion completed in:\n'
+ Math.floor(x/1000/60) + ' Minutes, '
+ Math.floor(x/1000%60) + ' Seconds, and '
+ x%1000 + ' Milliseconds');
Copy link to clipboard
Copied
hi querty, my script finds the centroids, not the fat part like yours.
Copy link to clipboard
Copied
it's a nice looking script, I would like to find some time so I can pull it apart so I understand it.
when I first started playing with this idea in a script I wrongly said "better to find gravitational center and not just the center" or something...
the centroid of a 2d object is in essence its center of mass, or gravitational center.
when applying a label to an arbitrary shape my thought is that it is best to be positioned, centered in the fattest part of the object.
Copy link to clipboard
Copied
when applying a label to an arbitrary shape my thought is that it is best to be positioned, centered in the fattest part of the object.
and you did very well, brilliant way to find the fattest part.
Copy link to clipboard
Copied
but its so slow!
there has to be a better way!
even if its just to tweak the values for a more efficient strokewidth.
but there has to be a nice clean Math based solution.
Copy link to clipboard
Copied
Hi Qwertyfly!
Thanks for the work you've done! I tried to run a script on a bigger file, where the objects count are much more than in your example. The script worked for more than 4 hours and produced an error. "Loop Error, try resetting percentage to 1, and incroment to .8 in the script file".
I have a very powerful computer core i7, but a few restarts gave the result a maximum number 1 on one layer and no longer moved. In addition, the script has fulfilled so many cycles, I was even able to correct the code to the confirmation was sought after not 100 cycles, but 10000. In the end, nothing came of it. Perhaps it really is due to the file size, but my files will not be less than 1000 objects.
Please try find out what else you can do to script to work. Even if it will work slow, but correct.
Copy link to clipboard
Copied
You should not get that message unless you press no on the dialog that tells you the "Process function has run ... times on current object."
it does not care how many items are in the document.
this count topping out at 100 is how many time it tries to find the center of each shape.
increasing this will probably not fix the issue.
there are a few values which may fix this.
would it be possible for you to send me the file in question?
I would be happy to test it out for you.
Copy link to clipboard
Copied
Yes please, u can download 2 files, this is my simplest one example.
The first file is original, second is result that i want to have.
Copy link to clipboard
Copied
even before it hangs up on a shape it does strange things.
the positions are all off.
this is due to the poor job illustrator does of expanding outlines.
This will actually take a bit of time to nut out the best way to get around the odd points illustrator adds.
I'll let you know once I have it working.
Copy link to clipboard
Copied
Dear Qwertyfly, if you happen to find the time to view the file, please let me know.
Copy link to clipboard
Copied
I viewed the files and was getting the errors you mentioned above.
it seems to be due to the way illustrator produces strange spiked anomalies when expanding outlines.
this involves a rethink as to how to achieve this.
at this point I am unsure as to the best way to make this work.
when I get a chance I will tackle this again. if I come up with anything I will let you know.
Copy link to clipboard
Copied
Hey did you already make sure to use "rounded corners" when using a stroke?
Copy link to clipboard
Copied
I did not!,
I'm not sure it will make a difference as it's one of those buggy things illustrator does.
But would be worth a try.
I'll give this a go over the next few days.
Thanks again Silly
Copy link to clipboard
Copied
Or set the Miter Limit of the stroke to something low line 1 or 2.