5 Replies Latest reply on Jun 18, 2015 12:40 PM by AllegraColumbia

    Logarithmic value returned for selection bounds

    AllegraColumbia

      I have a script that has been working to compare all the page contents (select all, get bounds) bounds to the page bounds. Sometimes the page contents are a single group. It has been working fine, but now it has started returning one or more of the selection bounds as a logarithmic number which makes the comparison test fail. Any ideas?

        • 1. Re: Logarithmic value returned for selection bounds
          [Jongware] Most Valuable Participant

          A logarithmic number - you mean exponential notation, such as "1.6441e-3 pt"? As long as your numbers are .. well, numbers, Javascript should have no problems comparing them against others. Is it possible you converted the numbers to strings somewhere?

          • 2. Re: Logarithmic value returned for selection bounds
            AllegraColumbia Level 1

            Thanks in advance for any help!

             

            Probably too little info if nobody has seen this issue.

             

            Here is the result I get after running the attached script twice on a business card with a box that does not fill the page bounds. The first run of the script determines a box the size of the page bounds needs to be drawn and draws it. The second  time I run it, it thinks the drawn box is outside of the page bounds because the selection bounds returns -1.57898387244693-15,0,2,3.5. If I select and re-enter the dimensions for the drawn box, it's back to 0,0,2,3.5.

             

            I do convert the arrays to a string to test equivalency, but I don't think that's the problem.

             

            I am not an expert and have done some cobbling together from other examples so the code is probably not the best. Here's the script:

             

            var myDocument = app.activeDocument;

            var myPageBounds = myDocument.pages[0].bounds;

            var myTargetPoint = [0,0];

            myDocument.zeroPoint = [0,0];

             

            app.select(NothingEnum.nothing);

            var mySelect = myDocument.pages[0].pageItems.everyItem().select();

            var mySelectionBounds = (myDocument.selection[0].geometricBounds);

            mySelectionBoundsString = mySelectionBounds.join();

            myPageBoundsString = myPageBounds.join();

             

            var myPageX1 = myPageBounds[1];

            var myPageY1 = myPageBounds[0];

            var myPageX2 = myPageBounds[3];

            var myPageY2 = myPageBounds[2];

             

            var mySelectionX1 = mySelectionBounds[1];

            var mySelectionY1 = mySelectionBounds[0];

            var mySelectionX2 = mySelectionBounds[3];

            var mySelectionY2 = mySelectionBounds[2];

             

            if (mySelectionX1 < myPageX1){

                alert ("Items outside of page...");

                    myDocumentReady = false;

                }

            else if (mySelectionY1 < myPageY1){

                alert ("Items outside of page...");

                        myDocumentReady = false;

            }

            else if (mySelectionX2 > myPageX2){

                alert ("Items outside of page...");

                        myDocumentReady = false;

            }

            else if (mySelectionY2 > myPageY2){

                alert ("Items outside of page...");

                        myDocumentReady = false;

            }

            else {

                myDocumentReady = true;

                }

             

            if (myDocumentReady == true){

               

            if (mySelectionBoundsString == myPageBoundsString){

            } else {

            drawBox (myPageBounds);

            }

            }

             

            function drawBox (myPageBounds) {

                  var recProps = {

                    fillColor: 'None',

                    strokeColor: 'None',

                    strokeWeight: 0,

                    };

             

            recProps.geometricBounds = myPageBounds;

            var myRectangle = myDocument.pages[0].rectangles.add(recProps);

            }

             

            alert(mySelectionBounds);

            • 3. Re: Logarithmic value returned for selection bounds
              Marc Autret Level 4

              Hi AllegraColumbia,

               

              This is a rounding error. The string "-1.57898387244693e-15" represents a number which is very close to zero. In JavaScript, the usual machine epsilon is Math.pow(2, -53), but in InDesign metrics the floating-point precision is also impacted by internal conversions of measurement units, so I don't know the exact machine epsilon of InDesign coordinates. Empirically, one might consider that differences lower than 1e-10 are not perceptible—at least in points units. When you compare coordinates, take into account this epsilon value.

               

              Also, your script doesn't properly compute the bounds of the entire selection. The code myDocument.selection[0].geometricBounds only considers the first selected item. Better is to implement a min-max routine to compute the area delimited by a set of page items. See getAllBounds() in the following code.

               

              const E = 1e-10; // machine epsilon
              
              function getAllBounds(/*[t,l,b,r][]*/a)
              {
                  var t = 1/0, l = 1/0,
                      b = -1/0, r = -1/0,
                      i = a.length,
                      gb;
              
                  while( i-- )
                      {
                      gb = a[i];
                      gb[0] < t && (t=gb[0]); // top
                      gb[1] < l && (l=gb[1]); // left
                      gb[2] > b && (b=gb[2]); // bottom
                      gb[3] > r && (r=gb[3]); // right
                      }
                  return [t,l,b,r];
              }
              
              var myDocument = app.activeDocument;
              
              // Reset the origin *before* you grab bounds.
              // ---
              myDocument.zeroPoint = [0,0];
              
              var myPageBounds = myDocument.pages[0].bounds;
              
              // Using a selection doesn't help.
              // Compute min-max bounds instead.
              // ---
              var allBounds = getAllBounds(myDocument.pages[0].pageItems.everyItem().geometricBounds);
              
              // Use machine epsilon (E) when comparing coordinates
              // ---
              var myDocumentReady = myPageBounds[0]-E <= allBounds[0]
                  && myPageBounds[1]-E <= allBounds[1]
                  && myPageBounds[2]+E >= allBounds[2]
                  && myPageBounds[3]+E >= allBounds[3];
              
              if( !myDocumentReady ) alert ("Items outside of page...");
              

               

              Hope that helps.

               

              @+

              Marc

              • 4. Re: Logarithmic value returned for selection bounds
                [Jongware] Most Valuable Participant

                Marc Autret wrote:

                ... Empirically, one might consider that differences lower than 1e-10 are not perceptible—at least in points units.

                 

                You can say that again – you're off by seven zeroes. The value I mentioned as example, 1.6441e-3 pt, was not totally random. It's the wavelength of yellow light, and so, per definition, you cannot "see" differences lower than that (I was actually surprised it's not less than 1/600th of a point. TeX's native unit is 10 times smaller!).

                • 5. Re: Logarithmic value returned for selection bounds
                  AllegraColumbia Level 1

                  Forgot to offer thanks for the correction to exponential!

                   

                  And I appreciate the script suggestions. Good thinking to set the origin before checking the bounds! I hardly ever move the origin and setting it was actually for something else in the complete script later on.

                   

                  I does seem like I get the bounds of all selected objects returned. Using CS5 and CS6. That might have changed with CC.

                   

                  As an experiment. I tried running the script on a letter sized page and it seems to have no problems. However, my script is for a business card sized page (3.5 x 2).

                   

                  I still have the basic question though as to why when I have just drawn a box using integer values, the next time I check the bounds, it returns an exponential value for one or more of the coordinates.