11 Replies Latest reply on Nov 6, 2008 8:00 PM by (Simon_Paterson)

    [JS] Page item (rectangle frame) width and height

    (Simon_Paterson) Level 1
      Following is my attempt at writing a function for width and height. It appears to work on rotated and sheared objects. Can anyone tell me if I'm on the right track?

      >function WidthAndHeight(myRectangle) // Returns an array [width,height]
      {
      ]var myRectangleTopLeft = myRectangle.resolve(AnchorPoint.topLeftAnchor, CoordinateSpaces.pasteboardCoordinates, true);

      var myRectangleTopRight = myRectangle.resolve(AnchorPoint.topRightAnchor, CoordinateSpaces.pasteboardCoordinates, true);

      var myRectangleBottomLeft = myRectangle.resolve(AnchorPoint.bottomLeftAnchor, CoordinateSpaces.pasteboardCoordinates, true);

      ]var d1x = (myRectangleTopRight[0][0] - myRectangleTopLeft[0][0]);

      var d1y = (myRectangleTopRight[0][1] - myRectangleTopLeft[0][1]);

      var myWidth = hypotenuse(d1x,d1y);

      var d2x = (myRectangleTopLeft[0][0] - myRectangleBottomLeft[0][0]);

      var d2y = (myRectangleTopLeft[0][1] - myRectangleBottomLeft[0][1]);

      var myHeight = hypotenuse(d2x,d2y);


      ]return [myWidth,myHeight];

      ]function hypotenuse(d1,d2)
      {
      ]]return Math.sqrt ( Math.pow(d1,2) + Math.pow(d2,2) );
      ]}

      }
        • 1. Re: [JS] Page item (rectangle frame) width and height
          Loic.Aigon Adobe Community Professional
          Hi,
          When I want to get w & h, I do this but don't claim it's a best way :

          function WidthAndHeight(myRectangle)
          {
          var gb = myRectangle.geometricBounds;
          var myWidth = gb[3]-gb[1];
          var myHeight = gb[2]-gb[0];
          return [myWidth,myHeight];
          }
          WidthAndHeight(myRectangle);
          Loic
          • 2. Re: [JS] Page item (rectangle frame) width and height
            Level 1
            Loic,

            Your method will give the wrong answers if the object is rotated. I'm not sure what the "right" answers are when an object is skewed.

            On the other hand, in seven years of scirpting InDesign, I've yet to need the width or height of a rotated frame (except for the occasional instance where the rotation was exactly 90 degrees).

            Dave
            • 3. Re: [JS] Page item (rectangle frame) width and height
              Loic.Aigon Adobe Community Professional
              Hi Dave,

              What about this one ?
              http://dl.free.fr/r7k3ooSxO

              This is an approach based on applying pathfinder actions onto a copy of the frame. It returns physically a frame with coordinates inside.

              Tell me what you think.

              Loic
              • 4. Re: [JS] Page item (rectangle frame) width and height
                Level 1
                It gives different answers if you rotate the rectangle, so I'm not sure what to think.

                Did you try Simon's script?

                Dave
                • 5. Re: [JS] Page item (rectangle frame) width and height
                  Level 1
                  Simon's gives the same answers when you rotate, but it looks like the answers are always in points, no matter your ruler settings.

                  Dave
                  • 6. Re: [JS] Page item (rectangle frame) width and height
                    Loic.Aigon Adobe Community Professional
                    Hi Simon, Dave,
                    Please help me understand because I feel like I don't get the idea. I made this picture. Could you tell me if you look for answer A or B or maybe another one ?
                    http://img201.imageshack.us/my.php?image=widthandheighttl1.gif
                    Loic
                    • 7. Re: [JS] Page item (rectangle frame) width and height
                      Level 1
                      I can't answer your question because I can't get my mind around the impact of skewing. When it comes to rotation, the objective is to get the same answer for width and height no matter the angle of rotation.

                      Perhaps the same is true for skewing.

                      So, the answer is, the height and width of the object are needed as their original height and width, so you can (for example) make the object an inch wider and the result will be an inch-wider object subjected to the same rotation and skewing as the original.

                      The need for this kind of stuff comes up so infrequently in my work, that I have to think it through from first-principles when faced with the problem.

                      But, for example, say there were text in that box of yours and the text is overset. You want to make the box "taller" so the text is not overset. That's the kind of scenario where you need the "de-transformed" height and width so you can adjust one or both of them and achieve the same kind of logic for dealing with overset text on one of these frames as you would if it were just sitting there untransformed.

                      Dave
                      • 8. Re: [JS] Page item (rectangle frame) width and height
                        (Simon_Paterson) Level 1
                        Hi Loic,

                        I think your Figure A is what InDesign returns as the geometric bounds property: the overall rectangle which holds the item.

                        My take the way InDesign sees width and height of a sheared object is something like this: http://www.bookhouse.ath.cx/ShearedFrames.png

                        Shearing does introduce some interesting values for width and height, often different to what might be expected. But I think, in simple terms, it is the length of each side of the object, which is essentially what my function measures, and I checked the values being returned from the function to make sure they were the same as what InDesign displayed in the UI.

                        The way I envisage it, shearing has the effect of stretching the length of one side of the object, which can be seen in this exaggerated example: http://www.bookhouse.ath.cx/ReallyShearedFrame.png

                        Hope this helps.

                        (BTW, great illustration! My attempt is much more lame.)
                        • 9. Re: [JS] Page item (rectangle frame) width and height
                          (Simon_Paterson) Level 1
                          Dave, you are absolutely right (no surprise here) about always returning points. I'm not sure, but I think this may actually be an InDesign bug. At the end of the 'resolve' method the 'true' value is meant to indicate 'use ruler units', I believe. Having read the documentation, however, it does seem like certain transformation coordinate spaces functions only work in points.

                          To make this a more complete function, I've updated it to include a conversion to the current ruler units. I'm using the UnitValue object, and perhaps I'm misunderstanding something, but I cannot easily convert to a new UnitValue using the ruler measurements enumerations (it requires a string value to represent the target units). So I've had to include a switch function to get from the enumeration to the string value. Also, the UnitValue object does not seem to work with agates, and I haven't gone so far as to write my own conversion function for that, so the function has to exit with an alert if the user has agates as their ruler units.

                          If anyone can offer a more elegant way of dealing with this, it would be great. Or even better, some insight into why the resolve method does not seem to honour the ruler units. This _is_ getting a bit over-the-top for a simple width and height function. Maybe Adobe will consider just adding the property to the page item and putting us all (well, certainly me, anyway) out of our misery (I've put in a feature request).

                          > function WidthAndHeight(myRectangle) // Returns an array [width,height]

                          ] {
                          ]] var myRectangleTopLeft = myRectangle.resolve(AnchorPoint.topLeftAnchor, CoordinateSpaces.pasteboardCoordinates, true);

                          var myRectangleTopRight = myRectangle.resolve(AnchorPoint.topRightAnchor, CoordinateSpaces.pasteboardCoordinates, true);

                          var myRectangleBottomLeft = myRectangle.resolve(AnchorPoint.bottomLeftAnchor, CoordinateSpaces.pasteboardCoordinates, true);

                          ]] var d1x = (myRectangleTopRight[0][0] - myRectangleTopLeft[0][0]);

                          var d1y = (myRectangleTopRight[0][1] - myRectangleTopLeft[0][1]);

                          var myWidth = hypotenuse(d1x,d1y);

                          var d2x = (myRectangleTopLeft[0][0] - myRectangleBottomLeft[0][0]);

                          var d2y = (myRectangleTopLeft[0][1] - myRectangleBottomLeft[0][1]);

                          var myHeight = hypotenuse(d2x,d2y);


                          ]] var myHorizontalUnits = unitsEnumToString(app.documents[0].viewPreferences.horizontalMeasurementUnits);

                          var myVerticalUnits = unitsEnumToString(app.documents[0].viewPreferences.verticalMeasurementUnits);

                          ]] myWidth = new UnitValue(myWidth,"points");

                          myHeight = new UnitValue(myHeight,"points");

                          ]] myWidth = myWidth.as(myHorizontalUnits);

                          myHeight = myHeight.as(myVerticalUnits);

                          ]] return [myWidth,myHeight];

                          ]] function hypotenuse(d1,d2)

                          ]]] {

                          ]]]] return Math.sqrt ( Math.pow(d1,2) + Math.pow(d2,2) );

                          ]]] }

                          ]] function unitsEnumToString(myUnitsEnum)

                          ]]] {

                          ]]]] switch(myUnitsEnum)

                          ]]]]] {

                          ]]]]]] case 2054188905 :

                          ]]]]]]] return "points";

                          ]]]]]] case 2054187363 :

                          ]]]]]]] return "picas";

                          ]]]]]] case 2053729891 :

                          ]]]]]]] return "inches";

                          ]]]]]] case 2053729892 :

                          ]]]]]]] return "inches decimal";

                          ]]]]]] case 2053991795 :

                          ]]]]]]] return "millimeters";

                          ]]]]]] case 2053336435 :

                          ]]]]]]] return "centimeters";

                          ]]]]]] case 2053335395 :

                          ]]]]]]] return "ciceros";

                          ]]]]]] default :

                          ]]]]]]] alert("Cannot convert to the current ruler units. Sorry.");

                          exit();

                          ]]]]] }

                          ]]] }

                          ]] }
                          • 10. Re: [JS] Page item (rectangle frame) width and height
                            Level 1
                            Hi Simon,

                            This is a really nice function you've put together here--good job!

                            re: "[always returning points] I'm not sure, but I think this may actually be an InDesign bug."

                            Not exactly--this is the way it's supposed to work. The key points are that a.) "pasteboard coordinates" do not have to do with the pasteboard surrounding the spread that you see in the UI, b.) "spread coordinates" are based on the center of the spread, not the ruler location, and c.) both coordinate systems use points, and nothing else. I have to document this better than I have.

                            re: "At the end of the 'resolve' method the 'true' value is meant to indicate 'use ruler units', I believe."

                            That applies only to the values you enter in the method's location parameter.

                            re: "To make this a more complete function, I've updated it to include a conversion to the current ruler units. I'm using the UnitValue object, and perhaps I'm misunderstanding something, but I cannot easily convert to a new UnitValue using the ruler measurements enumerations (it requires a string value to represent the target units)."

                            Nice job, again. The trick is that UnitValue is an ExtendScript feature, whereas the MeasurementUnits enumeration is an InDesign feature. Neither knows about the other. It's a little bit complicated to explain how this came about--and has to do with the other applications that ExtendScript has to serve (Illustrator, Photoshop, etc.)--but the point is that you've done exactly the right thing.

                            Thanks,

                            Ole
                            • 11. Re: [JS] Page item (rectangle frame) width and height
                              (Simon_Paterson) Level 1
                              Thank you so much, Ole, for clearing that up. I understand the documentation a bit better now. I didn't realise the 'consider ruler units' was for the method's parameters, but that makes total sense now. I never find bugs in the InDesign scripting engine so I considered that the least likely possibility.

                              I figured the UnitValue thing was because of the object belonging to ExtendScript and that ExtendScript is used across applications; I was concerned that I may have been doing something the clunky way and certainly didn't want to do that. So I'm glad I have used a suitable approach.

                              Most of all I'm glad for the time you took to critique this function. A compliment from you is like a big, fat gold star from your favourite teacher. :)