1

I have an SVG with a few curved paths. I'd like to create n versions of this, by rotating them around as a group (360 / n degrees apart), around the center of the square-shaped canvas they're in, like this:

rotation example

Then, I'd like to save these into separate SVG files.

Based on some initial research, this should be possible in Illustrator. However, I can't even get it to rotate all objects as a group, I can only rotate each object around its center with:

doc = app.activeDocument;
sel = doc.pageItems;
for (var i = 0; i < sel.length; i++) {
    sel[i].rotate(30);
}

How could I do this? (I'm also open to any software alternative.)

  • Just group all the items before rotating. See my answer to Rotating a layer around centre and save file (72 times) – Cai May 26 '17 at 12:54
  • Use matrix manipulation! – joojaa May 26 '17 at 13:44
  • @Cai - So how do you group all items? I failed to find this on Google before and I can't seem to find it in your other answer either. – Attila Tanyi May 26 '17 at 14:34
  • 1
    You're right actually, I just said in comments of my other answer to group first (I meant in AI itself, not in the script, just select all and cmd/ctrl+G)... Do you need to do this with a number of SVGs or just the one? If it's only one then grouping in AI manually is easy enough – Cai May 26 '17 at 14:36
3

Quick primer into computer graphics programming. Whenever you are trying to do a compound transform it is best to compose the transform onto a matrix operation. Mainly because you can specify a complex transformation in one go.

OK so no we have to compute the bounds. But then you might rotate around a arbitrary point in some case too (this makes it easy).

#target illustrator

var doc = app.activeDocument;
var sel = doc.pageItems;
var bounds = calculate_bounds(sel);
var center = [(bounds[0]+bounds[2])/2,
              (bounds[1]+bounds[3])/2]

for (var i = 0; i < sel.length; i++) {
    rotate_around_global_pos(sel[i], 30, center);
}


/********* Support functions *********/

function rotate_around_global_pos(obj, ang, pos) {
    var rot = app.getRotationMatrix(15);
    var mov = app.getTranslationMatrix(pos[0], pos[1]);
    var inv = app.invertMatrix(mov);
    var mtx = app.concatenateMatrix(inv, rot);
    var mtx = concatenateMatrix(mtx, mov);

    obj.transform(mtx, 1, 1, 1, 1, 1, Transformation.DOCUMENTORIGIN);
}

function calculate_bounds(sel){
    var minX = Number.POSITIVE_INFINITY;
    var maxX = Number.NEGATIVE_INFINITY;
    var minY = Number.POSITIVE_INFINITY;
    var maxY = Number.NEGATIVE_INFINITY;


    for (i = 0; i < sel.length; i++){
        var item = sel[i];
        var bounds = sel[i].controlBounds;

        minX = Math.min( minX, bounds[0], bounds[2] );
        maxX = Math.max( maxX, bounds[0], bounds[2] );
        minY = Math.min( minY, bounds[1], bounds[3] );
        maxY = Math.max( maxY, bounds[1], bounds[3] );
    }
    return [maxX, maxY, minX, minY];
}
  • Thanks! The matrix-based rotation around an arbitrary point is exactly what I needed. I wanted to rotate around the center of the canvas (not the bounding rect of the object group) and export after each rotation, but changing this and combining with Cai's code in the other question yields the perfect result. I'll post my code in a minute. (Also, the first line of the rotate_around_global_pos function should be var rot = app.getRotationMatrix(ang); I think.) – Attila Tanyi Jun 1 '17 at 22:01
1

You could always record an action on one file (Window > Actions) and then run the rest as a batch using that action...

I did a test creating, saving out the first group and then rotating and saving out 7 copies... and it worked just fine:

Rotate and save action 1

Here is my action so you can see how I did it:

Rotate and save action 2

  • Thanks! This is probably the best way to do it using Actions. However, the reason I turned to the scripting approach is so that n as a parameter could be changed, and the rotation angle and output filenames would be automatically generated. (If n was changed to 100 instead of 8, you'd need to change the angle and do 92 Transform Again / Save As steps again manually.) – Attila Tanyi May 29 '17 at 17:05
1

Combining joojaa's matrix manipulation and Cai's SVG exporting loop, I ended up with this script:

#target illustrator

var doc = app.activeDocument;
var docDir = ( doc.path != '' ) ? doc.path : '~';

var n = 20,
    iterations = n - 1,
    angle = 360 / n,
    destFolder = 'rotated'; // output files are saved in this subfolder

rotateAndExport();

function rotateAndExport() {
    var pos = [doc.width / 2, doc.height / 2];
    var layer = doc.layers[0];
    exportFile(1); // save the original file into the output folder
    for ( var r = 0; r < iterations; r++ ) {
        for ( var j = 0; j < layer.pageItems.length; j++ ) {
            var item = layer.pageItems[j];
            rotate_around_global_pos(item, -angle, pos);
        }
        exportFile(r + 2);
    }
}

function pad(number) { // pad with a leading zero (%02d)
    if (number <= 9) number = "0" + number;
    return number;
}

function exportFile( iteration ) {
    // create folder if it doesn't exist
    var destPath = docDir + '/' + destFolder;
    if ( false == Folder( destPath ).exists ) {
        new Folder( destPath ).create();
    }

    // export options
    var destFile;
    var type;
    var exportOptions;

    var svgPath = destPath + '/';
    destFile = new File( svgPath + '/output_' + pad(iteration) + ".svg");

    type = ExportType.SVG;
    exportOptions = new ExportOptionsSVG();
    exportOptions.preserveEditability   = false;
    exportOptions.embedRasterImages     = true;
    exportOptions.embedAllFonts         = false;
    exportOptions.encoding              = SVGDocumentEncoding.UTF8;
    exportOptions.fontType              = SVGFontType.OUTLINEFONT;

    doc.exportFile( destFile, type, exportOptions );
}

function rotate_around_global_pos(obj, ang, pos) {
    var rot = app.getRotationMatrix(ang);
    var mov = app.getTranslationMatrix(pos[0], pos[1]);
    var inv = app.invertMatrix(mov);
    var mtx = app.concatenateMatrix(inv, rot);
    var mtx = concatenateMatrix(mtx, mov);

    obj.transform(mtx, 1, 1, 1, 1, 1, Transformation.DOCUMENTORIGIN);
}

This script creates a subfolder next to the file currently open, and saves n states, each of which are rotated clockwise with the same angle one after another. (The paths don't need to be grouped, and no additional rectangle needs to be added.)

0

If you are using an SVG file, you can open it in Adobe Illustrator. Then select all of your objects that you wish to rotate. Ctrl + A should do. Then right click and group them. Now, you can easily rotate them as one.

You can ungroup them later as well.

  • Thank you for your answer, but I'm afraid you missed the 'script' part of my question. In my case, n > 1 (it's around 20), so I'd like to avoid doing this manually. – Attila Tanyi May 26 '17 at 14:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.