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

Auto picture grid layout script

Participant ,
Sep 17, 2023 Sep 17, 2023

Copy link to clipboard

Copied

Hello 


The script below sorta works but fails in bits - below is the background 

I want to make a script which can auto make a grid of graphic frames of different sizes, neatly laid out like the screenshot below 

 

SmythWharf_0-1694964315471.png

 

I want the user to draw a retectangle the size of the area they want the grid to be, then run the script which prompts the amount of boxes and gutter between them 

the script then auto makes a grid of random sizes mainting the gutter

the script could make the random box sizes based on a multiple of cell size if one was to think of the space being devided into cells - rows and columns so frames could span 1x3 or 2x2 etc 


My script generates the boxes at different sizes which seems good 

but it doesnt make them big enough to match the same size area as the user selection nor does it follow the gutter width, nor does it prevent overlapping.

Any ideas on where to fix it  - also i do have a scipt I made which makes a grid based on user input which is sorta what I am using the base this new script on.

Thanks all

Tricky one this!!



This is the code for the auto picture layout 

// Define a dialog
var dialog = app.dialogs.add({ name: "Create Graphic Frames" });

// Create a dialog column
var dialogColumn = dialog.dialogColumns.add();

// Create a dialog row for the number of boxes
var numBoxesRow = dialogColumn.dialogRows.add();
numBoxesRow.staticTexts.add({ staticLabel: "Number of Boxes:" });
var numBoxesField = numBoxesRow.textEditboxes.add({ minWidth: 80 }); // Adjust the minWidth value

// Create a dialog row for gutter width
var gutterRow = dialogColumn.dialogRows.add();
gutterRow.staticTexts.add({ staticLabel: "Gutter Width:" });
var gutterField = gutterRow.textEditboxes.add({ minWidth: 80 }); // Adjust the minWidth value

// Show the dialog and get user input
if (dialog.show() === true) {
  // Get the number of boxes and gutter width from user input
  var numBoxes = parseInt(numBoxesField.editContents);
  var gutterWidth = parseFloat(gutterField.editContents);

  // Convert the user's preference to points
  var gutterWidthPoints;
  if (app.activeDocument.viewPreferences.horizontalMeasurementUnits === MeasurementUnits.inches) {
    gutterWidthPoints = gutterWidth * 72; // Convert inches to points
  } else if (app.activeDocument.viewPreferences.horizontalMeasurementUnits === MeasurementUnits.millimeters) {
    gutterWidthPoints = gutterWidth * 2.83465; // Convert millimeters to points
  } else if (app.activeDocument.viewPreferences.horizontalMeasurementUnits === MeasurementUnits.centimeters) {
    gutterWidthPoints = gutterWidth * 28.3465; // Convert centimeters to points
  } else {
    // By default, assume the user's input is already in points
    gutterWidthPoints = gutterWidth;
  }

  // Check if the user entered valid numbers
  if (!isNaN(numBoxes) && numBoxes > 0 && !isNaN(gutterWidthPoints) && gutterWidthPoints >= 0) {
    // Get the user's selection
    var userSelection = app.selection[0];

    // Check if the selection is valid and is a rectangle or other suitable shape
    if (userSelection instanceof Rectangle || userSelection instanceof Oval) {
      var doc = app.activeDocument;
      var bounds = userSelection.geometricBounds;

      // Calculate the width and height of each cell
      var cellWidth = (bounds[3] - bounds[1]) / numBoxes;
      var cellHeight = (bounds[2] - bounds[0]) / numBoxes;

      // Calculate the total area of the user's selection
      var userSelectionArea = (bounds[3] - bounds[1]) * (bounds[2] - bounds[0]);

      // Create an array to store whether a cell is occupied
      var cellOccupied = [];

      // Initialize the array to all false (unoccupied)
      for (var i = 0; i < numBoxes; i++) {
        cellOccupied[i] = [];
        for (var j = 0; j < numBoxes; j++) {
          cellOccupied[i][j] = false;
        }
      }

      // Create the graphic frames based on the user's input
      for (var k = 0; k < numBoxes; k++) {
        var i, j;
        var tries = 0; // Track attempts to fit the frame
        var maxTries = numBoxes * numBoxes; // Maximum attempts before giving up

        do {
          // Generate random coordinates within the grid
          i = Math.floor(Math.random() * numBoxes);
          j = Math.floor(Math.random() * numBoxes);
          tries++;

          // Calculate random dimensions for the box
          var randomRows = Math.floor(Math.random() * (numBoxes - i)) + 1;
          var randomCols = Math.floor(Math.random() * (numBoxes - j)) + 1;

          // Calculate the geometric bounds for the frame
          var frameX1 = bounds[0] + i * cellWidth;
          var frameY1 = bounds[1] + j * cellHeight;
          var frameX2 = frameX1 + randomCols * cellWidth;
          var frameY2 = frameY1 + randomRows * cellHeight;

          // Calculate the area of the new box
          var newBoxArea = (frameX2 - frameX1) * (frameY2 - frameY1);

          // Check if the frame fits inside the user's selection and the total area is not exceeded
          var frameFits = frameX2 <= bounds[3] && frameY2 <= bounds[2] && (userSelectionArea - newBoxArea) >= 0;

          if (frameFits) {
            // Update the occupied status of cells
            for (var x = i; x < i + randomRows && x < numBoxes; x++) {
              for (var y = j; y < j + randomCols && y < numBoxes; y++) {
                cellOccupied[x][y] = true;
              }
            }

            // Create the graphic frame
            var frame = doc.pages[0].rectangles.add();
            frame.geometricBounds = [frameY1, frameX1, frameY2, frameX2];

            // Update the total area
            userSelectionArea -= newBoxArea;
          }
        } while (!frameFits && tries < maxTries);

        // If the maximum number of tries is reached, exit the loop
        if (tries === maxTries) {
          alert("Unable to fit all boxes inside the selection while maintaining the same area.");
          break;
        }
      }

      // Remove the original user selection
      userSelection.remove();
    } else {
      alert("Please select a suitable shape (e.g., a rectangle or oval) to create graphic frames within.");
    }
  } else {
    alert("Please enter valid numbers for the number of boxes and gutter width.");
  }

  // Close the dialog
  dialog.destroy();
} else {
  // User canceled the dialog
  dialog.destroy();
}



 And this is the working code for the grid maker 

// Define a dialog
var dialog = app.dialogs.add({ name: "Create Graphic Frames" });

// Create a dialog column
var dialogColumn = dialog.dialogColumns.add();

// Create a dialog row for number of rows
var numRowsRow = dialogColumn.dialogRows.add();
numRowsRow.staticTexts.add({ staticLabel: "Number of Rows:" });
var numRowsField = numRowsRow.textEditboxes.add({ minWidth: 80 }); // Adjust the minWidth value

// Create a dialog row for number of columns
var numColsRow = dialogColumn.dialogRows.add();
numColsRow.staticTexts.add({ staticLabel: "Number of Columns:" });
var numColsField = numColsRow.textEditboxes.add({ minWidth: 80 }); // Adjust the minWidth value

// Create a dialog row for gutter width
var gutterRow = dialogColumn.dialogRows.add();
gutterRow.staticTexts.add({ staticLabel: "Gutter Width:" });
var gutterField = gutterRow.textEditboxes.add({ minWidth: 80 }); // Adjust the minWidth value

// Show the dialog and get user input
if (dialog.show() === true) {
  // Get the number of rows and columns from user input
  var numRows = parseInt(numRowsField.editContents);
  var numCols = parseInt(numColsField.editContents);

  // Get the gutter width from user input (assuming user enters value in their preferred unit)
  var gutterWidth = parseFloat(gutterField.editContents);

  // Convert the user's preference to points
  var gutterWidthPoints;
  if (app.activeDocument.viewPreferences.horizontalMeasurementUnits === MeasurementUnits.inches) {
    gutterWidthPoints = gutterWidth * 72; // Convert inches to points
  } else if (app.activeDocument.viewPreferences.horizontalMeasurementUnits === MeasurementUnits.millimeters) {
    gutterWidthPoints = gutterWidth * 2.83465; // Convert millimeters to points
  } else if (app.activeDocument.viewPreferences.horizontalMeasurementUnits === MeasurementUnits.centimeters) {
    gutterWidthPoints = gutterWidth * 28.3465; // Convert centimeters to points
  } else {
    // By default, assume the user's input is already in points
    gutterWidthPoints = gutterWidth;
  }

  // Check if the user entered valid numbers
  if (!isNaN(numRows) && numRows > 0 && !isNaN(numCols) && numCols > 0 && !isNaN(gutterWidthPoints) && gutterWidthPoints >= 0) {
    // Get the user's selection
    var userSelection = app.selection[0];

    // Check if the selection is valid and is a rectangle or other suitable shape
    if (userSelection instanceof Rectangle || userSelection instanceof Oval) {
      var doc = app.activeDocument;
      var bounds = userSelection.geometricBounds;

      // Calculate the total available width and height for frames
      var totalWidth = bounds[3] - bounds[1];
      var totalHeight = bounds[2] - bounds[0];

      // Calculate the width and height of each frame including gutter
      var frameWidth = (totalWidth - (numCols - 1) * gutterWidthPoints) / numCols;
      var frameHeight = (totalHeight - (numRows - 1) * gutterWidthPoints) / numRows;

      // Create a grid of graphic frames based on the user's input and within the selection bounds
      for (var i = 0; i < numRows; i++) {
        for (var j = 0; j < numCols; j++) {
          var frame = doc.pages[0].rectangles.add();
          frame.geometricBounds = [
            bounds[0] + i * (frameHeight + gutterWidthPoints),
            bounds[1] + j * (frameWidth + gutterWidthPoints),
            bounds[0] + (i + 1) * (frameHeight + gutterWidthPoints) - gutterWidthPoints,
            bounds[1] + (j + 1) * (frameWidth + gutterWidthPoints) - gutterWidthPoints
          ];
        }
      }

      // Remove the original user selection
      userSelection.remove();
    } else {
      alert("Please select a suitable shape (e.g., a rectangle or oval) to create graphic frames within.");
    }
  } else {
    alert("Please enter valid numbers for the number of rows, columns, and gutter width.");
  }

  // Close the dialog
  dialog.destroy();
} else {
  // User canceled the dialog
  dialog.destroy();
}



TOPICS
How to , Scripting , SDK

Views

216

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
Participant ,
Sep 17, 2023 Sep 17, 2023

Copy link to clipboard

Copied

LATEST

Okay differnt idea but working below 
makes a random grid based on user bounding box size 

no user input - that part i can make later

// Create a reference to the active document
var doc = app.activeDocument;

// Check if a rectangle is selected
if (app.selection.length > 0 && app.selection[0] instanceof Rectangle) {
    var userRectangle = app.selection[0];

    // Get the bounds of the user's rectangle
    var userBounds = userRectangle.geometricBounds;

    // Define the grid parameters
    var numRows = 5; // Number of rows
    var numCols = 5; // Number of columns

    // Calculate the width and height of the grid
    var gridWidth = userBounds[3] - userBounds[1];
    var gridHeight = userBounds[2] - userBounds[0];

    // Calculate the maximum random width that can fit within the available space without overlapping
    var maxRandomWidth = gridWidth / numCols;

    // Calculate the height of each row based on the number of rows divided by the user's selected box height
    var rowHeight = gridHeight / numRows;

    // Initialize a grid to keep track of used cells
    var usedCells = [];

    // Loop through rows
    for (var i = 0; i < numRows; i++) {
        usedCells[i] = []; // Create a new row

        // Loop through columns
        for (var j = 0; j < numCols; j++) {
            // Check if the cell is already used
            if (!usedCells[i][j]) {
                // Calculate the position for each box
                var xPosition = userBounds[1] + j * maxRandomWidth;
                var yPosition = userBounds[0] + i * rowHeight;

                // Calculate the remaining space in the row
                var remainingSpaceInRow = gridWidth - j * maxRandomWidth;

                // Calculate the maximum random width for this box based on the remaining space in the row
                var maxRandomWidthForBox = Math.min(maxRandomWidth, remainingSpaceInRow);

                // Generate a random value for the width (up to a maximum of 3)
                var randomWidth = maxRandomWidthForBox * (Math.floor(Math.random() * 3) + 1);

                // Check if this is the last box in the row
                if (j === numCols - 1) {
                    // Calculate the width that fits within the remaining space without exceeding the bounds
                    var widthToFit = gridWidth - (j * maxRandomWidth);
                    randomWidth = Math.min(widthToFit, maxRandomWidthForBox);
                }

                // Create a new rectangle (box) inside the user's rectangle
                var box = doc.rectangles.add();
                var left = xPosition;
                var top = yPosition;
                var right = left + randomWidth;
                var bottom = top + rowHeight;
                box.geometricBounds = [top, left, bottom, right];
                box.fillColor = doc.swatches.itemByName("Black");

                // Mark the cells as used
                for (var k = 0; k < Math.ceil(randomWidth / maxRandomWidth); k++) {
                    for (var l = 0; l < 1; l++) {
                        if (i + l < numRows && j + k < numCols) {
                            usedCells[i + l][j + k] = true;
                        }
                    }
                }
            }
        }
    }

    // Delete the original user-drawn rectangle
    userRectangle.remove();
} else {
    alert("Please select a rectangle drawn by the user.");
}




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