'Random' color AI script with no adjacent colors the same

Community Beginner ,
Jan 04, 2021 Jan 04, 2021

Copy link to clipboard

Copied

Could an Illustrator script like RandomSwatchesFill be modified to apply colors in such a way that no two colors from a group of swatches would be repeated in shapes that immediately border each other? I don't think this is truly random, but it's meant to make the distribution of colors feel more varied.

 

From what I've seen online, this would be an application of the four color theorem — or whatever number of colors are involved. For my own purposes, I would typically have more colors in a group of swatches — at least five or more.

 

Appreciate any insights and guidance!

TOPICS
Draw and design, Feature request, How to, Scripting, Third party plugins

Views

274

Likes

translate

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
Enthusiast ,
Jan 06, 2021 Jan 06, 2021

Copy link to clipboard

Copied

Firstly, you'll need to define what "adjacent" means in terms of path items in Illustrator.  

Likes

translate

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 Beginner ,
Jan 09, 2021 Jan 09, 2021

Copy link to clipboard

Copied

By adjacent, I mean shapes that immediately border each other. In my case, the simplest example might be a checkerboard-like grid where colors are assigned so that no squares that border each other are colored the same. Thanks.

Likes

translate

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
Enthusiast ,
Jan 10, 2021 Jan 10, 2021

Copy link to clipboard

Copied

It could be done using an adjacency matrix, but I'm not familiar with implementing graphs in JS. 

Likes

translate

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
Enthusiast ,
Feb 27, 2021 Feb 27, 2021

Copy link to clipboard

Copied

On second thought, for the simplest case (as you describe), no adjacency matrix is required. A usual matrix used to compare the color of a path item with that of the path items above and to the left will suffice.

Untitled99.png

 

// run in CMYK color mode
var f = 2.83465;
var string1 = prompt("Enter rows-space-columns", "10 10");
var splitString1 = string1.split(" ");
var rows = Number(splitString1[0]), columns = Number(splitString1[1]);
var ABRect = app.activeDocument.artboards[0].artboardRect;
var paths =  app.activeDocument.pathItems;
var w = h = 20 * f, sumW = w * rows, sumH = h * columns;
var top = ABRect[3] / 2 + sumH / 2;
for (var i = 0; i < columns; i++) {
    var left = ABRect[2] / 2 - sumW / 2;
    for (var j = 0; j < rows; j++) {
        var rect0 = paths.rectangle(top, left, w, h);
        left = left + w;
    }
    top = top - h;
}
// create matrix 
var x = rows * columns - 1;
var matrix = [];
for (var i = 0; i < rows; i++) {
    matrix[i] = [];
    for (var j = 0; j < columns; j++) {
        matrix[i][j] = paths[x];
        x = x - 1;
    }
}
// compare color of pathItem to color of pathItems above and to left
var swatchez = app.activeDocument.swatches;
var c = swatchez["CMYK Cyan"].color, m = swatchez["CMYK Magenta"].color,
y = swatchez["CMYK Yellow"].color, k = swatchez["Black"].color;
for (var i = 0; i < rows; i++) {
    for (var j = 0; j < columns; j++) {
        var colorz = [{value:c, name:"c"}, {value: m, name:"m"}, {value: y, name:"y"}, {value: k, name:"k"}];
        for (var l = colorz.length - 1; l > -1 ; l--) {
            var color = colorz[l].value;
            if ((i > 0) && (color.cyan == matrix[i-1][j].fillColor.cyan && color.magenta == matrix[i-1][j].fillColor.magenta && color.yellow == matrix[i-1][j].fillColor.yellow && color.black == matrix[i-1][j].fillColor.black)) {
                colorz.splice(l, 1);
            } 
            if ((j > 0) && (color.cyan == matrix[i][j-1].fillColor.cyan && color.magenta == matrix[i][j-1].fillColor.magenta && color.yellow == matrix[i][j-1].fillColor.yellow && color.black == matrix[i][j-1].fillColor.black)) {
                colorz.splice(l, 1);
            }     
        }
        var index = Math.floor(Math.random() * colorz.length);
        matrix[i][j].fillColor = colorz[index].value;
    }
}

 

Likes

translate

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
Enthusiast ,
Mar 22, 2021 Mar 22, 2021

Copy link to clipboard

Copied

This is a first attempt at implementing of a graph using an adjacency list:

 

You will need a list of "edges" to enter into a text box when running the script.  A graph is a group of vertices (or nodes), which in our case represent paths, connected to each other by edges (or links), which in our case represent shared borders.  An edge is defined by the two vertices it connects. 

 

In the picture below, the paths on the left are represented by the graph on the right.  Each line is an edge.  For example, path1 shares a border with path2 and path3.  This is represented by the two edges "path1, path2" and "path1, path3".  You will need a list of all these edges. 

 

G1.jpg

 

This is a very frivolous implementation.  In fact, there's a bug I haven't fixed:  With more edges, there is a chance (about 1/10) that >4 colors will be needed. 

 

G2.jpg

 

G3.jpg

 

Test.ai file 

 

// instructions
// (1) name your paths
// (2) have a list of edges ready to input
// (3) an edge is a pair of path names separated by a comma
// (4) run in CMYK mode (or change the "color" part of the script to run in RGB mode)
// (5) select your paths and run

// input
var vertices = [];
for (var i = 0; i < selection.length;i++) {
    vertices.push(selection[i].name);
}
var test = 
"path1, path2\
path1, path3\
path2, path3\
path2, path4\
path2, path5\
path3, path5\
path3, path6\
path4, path5\
path5, path6";
var w = new Window ("dialog", "Edges");
var text1 = w.add ("edittext", [0, 0, 150, 140], "", {multiline: true, wantReturn: true});
text1.text = test;
w.add ("button", undefined, "OK");
w.show ();
var edges = text1.text.split("\n");
for (var i = 0; i < edges.length; i++) {
    edges[i] = edges[i].split(", ");
}
// create graph (adjacency list)
var list = {};
for (var i = 0; i < vertices.length; i++) {
    list[vertices[i]] = [];
}
for (var i = 0; i < edges.length; i++) {
    list[edges[i][0]].push(edges[i][1]);
    list[edges[i][1]].push(edges[i][0]);
}
// color
var paths =  app.activeDocument.pathItems;
var swatchez = app.activeDocument.swatches;
var c = swatchez["CMYK Cyan"].color,
m = swatchez["CMYK Magenta"].color,
y = swatchez["CMYK Yellow"].color,
k = swatchez["Black"].color;
for (var key in list) {
    var colorz = [c, m, y, k];
    for (var i = 0; i < list[key].length; i++) {
        for (var l = colorz.length - 1; l > -1 ; l--) {
            var c1 = colorz[l];
            var c2 = paths[list[key][i]].fillColor;
            if (c1.cyan == c2.cyan && c1.magenta == c2.magenta && 
                c1.yellow == c2.yellow && c1.black == c2.black) {
                colorz.splice(l, 1);
            }
        }
    }
    var index = Math.floor(Math.random() * colorz.length);
    if (!colorz[index]) {
        paths[key].fillColor = swatchez["White"].color;
    } else {
        paths[key].fillColor = colorz[index];
    }
}

 

Likes

translate

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 Beginner ,
Mar 22, 2021 Mar 22, 2021

Copy link to clipboard

Copied

That is pretty wicked, even as a demo! If I understand your implementation, for more complex figures, you would need to input values that help define the relative positions of each 'cell.'

 

Running the script now creates its own matrix. Would it be able to fill a custom-designed figure?

 

Appreciate your exploration.

Likes

translate

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
Enthusiast ,
Mar 24, 2021 Mar 24, 2021

Copy link to clipboard

Copied

"... for more complex figures, you would need to input values that help define the relative positions of each 'cell.'"

 

Correct.  

 

"Running the script now creates its own matrix. Would it be able to fill a custom-designed figure?"

 

Do you mean fill a path with the chequered pattern?  You could manually convert the outcome of the first script into a pattern and apply it to a path.  I suppose you could do it with a script, but again I have not done patterns with scripting.  

 

Likes

translate

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