Skip navigation
Currently Being Moderated

height parameter and math.random constraint

Apr 25, 2012 11:57 AM

I'm a scripting newbie. I'm trying to make a script that will...

  1. Grab all the objects I have selected
  2. Scale them down (in height) randomly to between 30% and 100% of their original height.

 

Here's what I have so far...

 

//get all the objects that are currently selected in the document

var selectedObjects = app.activeDocument.selection;

 

//decrease their size by a random number between 0% and 70%

for (var i=0; i<selectedObjects.length; i++){

          // gets the height of the current object

          var myHeights = selectedObjects[i].height;

          //take the height of the current object and scale it by a random percentage

          selectedObjects[i].height= Math.floor((Math.random()*myHeights)+.3);

}

 

 

And here's what it's doing, which is great...

ThisPartIsWorking.gif

But there are two problems I'm running into...

[Problem A] The height is getting scaled relative to the document instead of relative to the object. I would like to be able to rotate the objects around an axis manually before running the script and still have them scale each individual height relative to each object. So far, my script is scaling relative to the document x, y (I think).

ThisPartIsNotWorking.gif

I have set the pivot point for each of the rectangles to bottom center, but no dice. In the script, how do I tell it to use the anchor point of the object for scaling instead of the document?

 

[Problem B] I'm having trouble constraining the math.random to my values. For instance, notice here

ThisPartIsNotReallyWorking.gif

that the some of the rectangles end up teeny (smaller than 30% of the original height). How do I set constraints on the math.random so that it's easy for me to adjust the parameters? Right now I'm using math.floor but I'm obviously doing something wrong.

 

Any insight?

 
Replies
  • Currently Being Moderated
    Apr 25, 2012 1:47 PM   in reply to Petros_

    I made a quick search and found a function to get a random number.

     

    Use Resize to change the height instead of changing the height property, that'll take care of problem B.

     

    //get all the objects that are currently selected in the document
     
    var selectedObjects = app.activeDocument.selection;
     
    //decrease their size by a random number between 0% and 70%
     
    for (var i=0; i<selectedObjects.length; i++){
     
              //get the scale (random number between 30-100)
              var scale = randomXToY (30, 100);
              // scale Y only, from top
              selectedObjects[i].resize (100, scale, true, true, true, true, 1, Transformation.TOP)
     
    }
     
    //function to get random number upto m, by Roshan Bhattarai
    function randomXToY(minVal,maxVal,floatVal)
    {
      var randVal = minVal+(Math.random()*(maxVal-minVal));
      return typeof floatVal=='undefined'?Math.round(randVal):randVal.toFixed(floatVal);
    }
     
    //alert(randomXToY (30, 100));
    

     

     

    for problem [A], I would use a different approach. I would start with 1 object (since they're all the same) and duplicate it, scale it, and rotate it as many times as I need it to complete the circle. We can use a fixed point using these methods.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 25, 2012 2:39 PM   in reply to Petros_

    yes, the rotateAbout or scaleAbout or transformAbout all refer to those 9 points (I used TOP in the previous example), plus the document origin, which is the (0,0) you can change that manually or via script

     

    Transformation

    BOTTOM, LEFT

    BOTTOMLEFT, RIGHT

    BOTTOMRIGHT, TOP

    CENTER, TOPLEFT

    DOCUMENTORIGIN, TOPRIGHT

     

    edit:

    I re-read your previous question, the problem with rotating your object before you scale it is that it will get skewed like in you example. Scaling is only vertical and/or horizontal, you need to scale before rotate.

     

    Message was edited by: CarlosCanto

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 25, 2012 3:46 PM   in reply to Petros_

    I tried inserting BOTTOM instead of TOP, but it's still resizing based off an (imaginary to me) bounding box around the rotated rectangles

    try using BOTTOM on an unrotated item, to see how it works first, as I said, resize first, then rotate, otherwise shapes will not look right.

     

     

    doesn't Illustrator know that the object is actually a rectangle rotated 30 degrees?

    no, it just looks at the bounding box of a rotated or un-rotated objects.

     

    do you know where I can find information about the "true", "1", etc. values?:

    1. Scripting Reference

    2. Object Model Viewer

     

    they're the parameters to scale patterns, gradients, strokes, etc.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 25, 2012 5:30 PM   in reply to Petros_

    is there a reason you MUST rotate first?

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 26, 2012 12:54 AM   in reply to Petros_

    you lost me, I don't understand what you need. If you have to vary the rotation then no script can help you. If you have to rely on your eyes...same thing, that can't be scripted either.

     

    post a real example of what you need, with pretty pictures like you did in your fist post, we might come up with alternatives.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 26, 2012 12:45 PM   in reply to Petros_

    Petros, Carlos is right in the fact that this is much easier if you…

     

    dupe rectangle ( front/back what ever )

    scale the duplicate while verticle or horizontal

    rotate about some origin

     

    The other opition is to calculate all the points with math and create the paths… That's Jong business…

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 26, 2012 11:52 PM   in reply to Muppet Mark

    calculating all the points is just overkill, specially when there's really no need for it.

     

    Petros, here's a sample of the same thing we've been talking about, scale first, rotate next.

     

    randomRotate.PNG

     

    move your key object close to the (0,0), actually right above the (0,0) on the y axis or (0,radius) before running.

     

    //select ONE object before running
    var idoc = app.activeDocument;
    var copies = 20;
    var angle = 360/copies;
     
     
    var igroup = idoc.groupItems.add();
    var sel = idoc.selection[0];
    sel.move (igroup, ElementPlacement.PLACEATBEGINNING);
     
     
    var colorRef = new RGBColor;
    colorRef.red = 255;
     
     
    var ipath = igroup.pathItems[0];
    for (var i=0; i<copies; i++){
                        var idup = ipath.duplicate();
              //get the scale (random number between 30-100)
              var scale = randomXToY (0, 70);
                          $.writeln(scale);
              // scale Y only, from top
              idup.resize (100, scale, true, true, true, true, 1, Transformation.BOTTOM);
                         idup.rotate(angle*i,true,true,true,true,Transformation.DOCUMENTORIGIN);
                        idup.fillColor = colorRef;
    }
     
    ipath.hidden = true;
    //function to get random number upto m, by Roshan Bhattarai
    function randomXToY(minVal,maxVal,floatVal)
    {
      var randVal = minVal+(Math.random()*(maxVal-minVal));
      return typeof floatVal=='undefined'?Math.round(randVal):randVal.toFixed(floatVal);
    }
    
     
    |
    Mark as:
  • Currently Being Moderated
    Apr 27, 2012 3:54 AM   in reply to CarlosCanto

    Yep thats almost the exact same way I tested… as long as the starting shape is vertial or horizontal then it won't become a shear when scaled…

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 27, 2012 5:04 PM   in reply to Petros_

    (Just dropping in on something only slightly related)

     

    Your original random scaling factor fails because your random is no good. Instead of this

     

    h = Math.floor((Math.random()*myHeights)+.3);

     

    you should have used this

     

    h = Math.floor(myHeights*(0.3 + 0.7*Math.random()));

     

    That gives you a nice spread between 30% and 100% of the original heights.

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points