How do I make distance between concentric circles equal?

I’ve been beating my head against this for a while. The reason the rings are not aligned is because I initially started the project in Photoshop.

How can I the change the distance between rings to be a uniform measurement?

This is a close-up of the rings. Right now you can see that some
are closer than others.

enter image description here

This is a photo of the full image:

enter image description here


I’d say things like this are better done with automation. Imagine width of one of the items in the middle of your collection changes and you’ll have to rebuild half of the circles. Or you need to make all the circles 50% more wide. Oh man!

I don’t know Illustrator scripting, but in Photoshop it’s quite straightforward. Basically I have a data array with properties like name, value, color and I have a function that creates a shape layer in specific coordinates with a specific radius. Plus I have several additional parameters like a gap between the circles, a maximum width of a circle and a starting radius.

Using this data, in a loop I create a circle for each data entry. Center is always a document center, width is calculated linearly based on a maximum width and a maximum data value found, radius is calculated based on a width, previous radius and a gap.

Here’re different results based on different settings for a gap, starting radius and max width:

enter image description here

And the code I used:

function main()

    //data definitions
    var center = {
        x:"px") / 2,
        y:"px") / 2
    var gap = 3; // gap between circles
    var startRad = 200; // starting radius
    var maxWidth = 15; // maximum width
    var maxValue = -1; // stores maximum value found
    var width, i;

    var data = [
        color: [223,41,53],
        value: 22,
        name: "Jerelyn Pinkbeard"
        color: [65,39,34],
        value: 13,
        name: "Spiteful Christine Black"
        color: [223,160,110],
        value: 44,
        name: "Generous Christi"
        color: [12,243,187],
        value: 4,
        name: "Scrawny Tiphanie"
        color: [134,186,144],
        value: 12,
        name: "Cutthroat Deena The Spiteful"
        color: [5,47,95],
        value: 22,
        name: "Jerilyn Blackhate"
        color: [0,83,119],
        value: 60,
        name: "Tiphanie Generousparrot"
        color: [6,167,125],
        value: 33,
        name: "First Mate Christa The Scrawny"
        color: [213,198,122],
        value: 12,
        name: "Dread Pirate Geraldine"

    // START

    // first calculating maximum value of all data properties to use it later for linear transforms
    for (i = 0; i < data.length; i++)
        if (data[i].value > maxValue) maxValue = data[i].value;

    // creating circles
    for (i = 0; i < data.length; i++)
        //calculating width lineary based on maximum value found and maximum width possible
        width = linear(data[i].value, 0, maxValue, 0, maxWidth);

            x: center.x, // X center of the document
            y: center.y, // Y center of the document
            color: data[i].color, // color from my data
            width: width, // calculated width
            radius: startRad, // starting radius
            name: data[i].name // and a name

        startRad += width + gap; // updating starting radius with width and gap

    function createCircle(data)
        var desc2 = new ActionDescriptor();
        var ref1 = new ActionReference();
        desc2.putReference(cTID('null'), ref1);
        var desc3 = new ActionDescriptor();
        var desc4 = new ActionDescriptor();
        var desc5 = new ActionDescriptor();
        desc5.putDouble(cTID('Rd  '), 45.000001);
        desc5.putDouble(cTID('Grn '), 77.000003);
        desc5.putDouble(cTID('Bl  '), 113.000001);
        desc4.putObject(cTID('Clr '), cTID('RGBC'), desc5);
        desc3.putObject(cTID('Type'), sTID('solidColorLayer'), desc4);
        var desc6 = new ActionDescriptor();
        desc6.putInteger(sTID('unitValueQuadVersion'), 1);
        desc6.putUnitDouble(cTID('Top '), cTID('#Pxl'), data.y - data.radius);
        desc6.putUnitDouble(cTID('Left'), cTID('#Pxl'), data.x - data.radius);
        desc6.putUnitDouble(cTID('Btom'), cTID('#Pxl'), data.y + data.radius);
        desc6.putUnitDouble(cTID('Rght'), cTID('#Pxl'), data.x + data.radius);
        desc3.putObject(cTID('Shp '), cTID('Elps'), desc6);
        var desc7 = new ActionDescriptor();
        desc7.putInteger(sTID('strokeStyleVersion'), 2);
        desc7.putBoolean(sTID('strokeEnabled'), true);
        desc7.putBoolean(sTID('fillEnabled'), false);
        desc7.putUnitDouble(sTID('strokeStyleLineWidth'), cTID('#Pxl'), data.width);
        desc7.putUnitDouble(sTID('strokeStyleLineDashOffset'), cTID('#Pnt'), 0.000000);
        desc7.putDouble(sTID('strokeStyleMiterLimit'), 100.000000);
        desc7.putEnumerated(sTID('strokeStyleLineCapType'), sTID('strokeStyleLineCapType'), sTID('strokeStyleButtCap'));
        desc7.putEnumerated(sTID('strokeStyleLineJoinType'), sTID('strokeStyleLineJoinType'), sTID('strokeStyleMiterJoin'));
        desc7.putEnumerated(sTID('strokeStyleLineAlignment'), sTID('strokeStyleLineAlignment'), sTID('strokeStyleAlignOutside'));
        desc7.putBoolean(sTID('strokeStyleScaleLock'), false);
        desc7.putBoolean(sTID('strokeStyleStrokeAdjust'), false);
        var list1 = new ActionList();
        desc7.putList(sTID('strokeStyleLineDashSet'), list1);
        desc7.putEnumerated(sTID('strokeStyleBlendMode'), cTID('BlnM'), cTID('Nrml'));
        desc7.putUnitDouble(sTID('strokeStyleOpacity'), cTID('#Prc'), 100.000000);
        var desc8 = new ActionDescriptor();
        var desc9 = new ActionDescriptor();
        desc9.putDouble(cTID('Rd  '), data.color[0]);
        desc9.putDouble(cTID('Grn '), data.color[1]);
        desc9.putDouble(cTID('Bl  '), data.color[2]);
        desc8.putObject(cTID('Clr '), cTID('RGBC'), desc9);
        desc7.putObject(sTID('strokeStyleContent'), sTID('solidColorLayer'), desc8);
        desc7.putDouble(sTID('strokeStyleResolution'), 72.000000);
        desc3.putObject(sTID('strokeStyle'), sTID('strokeStyle'), desc7);
        desc2.putObject(cTID('Usng'), sTID('contentLayer'), desc3);
        desc2.putInteger(cTID('LyrI'), 2);
        executeAction(cTID('Mk  '), desc2, DialogModes.NO);

        if ( != undefined)
            var desc = new ActionDescriptor();
            var ref = new ActionReference();
            ref.putEnumerated(cTID("Lyr "), cTID("Ordn"), cTID("Trgt"));
            desc.putReference(cTID('null'), ref);
            var descName = new ActionDescriptor();
            descName.putString(cTID('Nm  '),;
            desc.putObject(cTID('T   '), cTID('Lyr '), descName);
            executeAction(cTID('setd'), desc, DialogModes.NO);
    } // end of createCircle()

    function linear(X, A, B, C, D)
        var Y = (X - A) / (B - A) * (D - C) + C
        return Y;

    function cTID(s)
        return app.charIDToTypeID(s);

    function sTID(s)
        return app.stringIDToTypeID(s);

app.activeDocument.suspendHistory("create circles", "main()");

Source : Link , Question Author : Alex Kuhn Art , Answer Author : Sergey Kritskiy

Leave a Comment