Skip to main content
bala281972
Known Participant
November 24, 2011
Answered

How to measure the distance using script

  • November 24, 2011
  • 2 replies
  • 5489 views

Hi

Is there any way to measure the distance of any photoshop document using the measure tool, by using the script. Given below the steps required by me. Hope i'm clear in my communications.

I searched the forums but couldnt find any suitable answers.

1.Open Photoshop document

2. Allow the user to draw the line using measure tool

3. alert the distance

Rgs

Anish

This topic has been closed for replies.
Correct answer Michael_L_Hale

I understand what you are saying and I agree that to match the measure tool the function would need to be changed. What I was trying to say was that it was originally written to work with left to right paths. The angle of a path made from left to right( that is pathPoint[0].anchor[0] is less than of pathPoint[3].anchor[0] when using a line tool path ) can only have an angle of +/- 90.

A path made from right to left needs to use different pathpoints and requries different math. Another factor for the mismatch is the measure tool rounds to the nearest whole pixel. Paths can use fractions of a pixel. The angle may not match exactly because of that rounding.

It's true all of those issues could be fixed and you are free to make any modifications you like.


This only works with CS5 as it now uses the ruler tool instead of a path. But it fixes all the issues talked about in this thread and well as some other differences between the original funciton and the data in the info panel.

It returns a custom object with angle and length properties if there is a ruler tool line in the active document and undefined it not. I was unsure if the length should be a unitValue or a number in the ruler units settings. I went with number because the info panel has different number of decimal places for the different units. And like the info panel if the ruler setting are set to percent the length value is blank

function getRulerToolLengthAndAngle(){

    var points = [];

    points.start = [];

    points.end = [];

    var desc = new ActionDescriptor();

    var ref = new ActionReference();

    ref.putProperty( charIDToTypeID('Prpr'), charIDToTypeID('RrPt') );

    ref.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );

    desc.putReference( charIDToTypeID('null'), ref );

    var desc = executeAction( charIDToTypeID('getd'), desc, DialogModes.NO );

    if( desc.hasKey( charIDToTypeID('Pts ') ) ){

        var pointList = desc.getList( charIDToTypeID('Pts ') );

        var startPointDesc = pointList.getObjectValue(0);

       

        points.start.push( startPointDesc.getUnitDoubleValue( charIDToTypeID( 'X   ' ) ) );

        points.start.push( startPointDesc.getUnitDoubleValue( charIDToTypeID( 'Y   ' ) ) );

        var endPointDesc = pointList.getObjectValue(2);

        points.end.push( endPointDesc.getUnitDoubleValue( charIDToTypeID( 'X   ' ) ) );

        points.end.push( endPointDesc.getUnitDoubleValue( charIDToTypeID( 'Y   ' ) ) );

       

        var res = {};

        res.toString = function(){ return 'RulerTool Info';};

        var pointA = points.start;

        var pointB = points.end;

        if( pointA[0]<pointB[0] ){

            var a = Math.max(pointA[0],pointB[0])-Math.min(pointA[0],pointB[0]);

            var o = Math.max(pointA[1],pointB[1])-Math.min(pointA[1],pointB[1]);

            var ang = (180/Math.PI) * Math.atan2(o,a);

            if(pointA[1] < pointB[1]){//negative angle

                ang = -ang;

            };

            res.angle = ang.toFixed(1);

        }else{

            var a = Math.max(pointA[1],pointB[1])-Math.min(pointA[1],pointB[1]);

            var o = Math.max(pointA[0],pointB[0])-Math.min(pointA[0],pointB[0]);

            var ang = 180-((180/Math.PI) * Math.atan2(a,o));

            if(pointA[1] < pointB[1]){//negative angle

                ang = -ang;

            };

            res.angle = ang.toFixed(1);

        }

            if( app.preferences.rulerUnits == Units.PERCENT ){

                res.length = "";

            }else{

                var c = Math.sqrt((a*a)+(o*o));

                var length = new UnitValue( c, 'px');

                length.baseUnit = new UnitValue((1/app.activeDocument.resolution),'in');

                switch( app.preferences.rulerUnits ){

                    case Units.PIXELS: res.length = length.as('px').toFixed(2); break;

                    case Units.INCHES : res.length = length.as('in').toFixed(3); break;

                    case Units.CM: res.length = length.as('cm').toFixed(2); break;

                    case Units.MM: res.length = length.as('mm').toFixed(1); break;

                    case Units.POINTS: res.length = length.as('pt').toFixed(1); break;

                    case Units.PICAS: res.length = length.as('pc').toFixed(2); break;

                }

            }

        return res;

    }

}

var info = getRulerToolLengthAndAngle();

if(info != undefined ) alert('The ruler tool angle is: '+info.angle+'\nThe length is: '+info.length);

2 replies

Inspiring
November 24, 2011

You can have the user mark the part of the image to be measured with the pen or line shape tool. But if all the script is going to do is alert the user the distance, they could get that from using the measure tool and the info panel without a script.

At any rate here is a function to find the distance and angle of a line path made with either the pen or line tool.

//the code below is for the pen tool. If the path was made with the line tool replace pathPoints[1] with pathPoints[3]

  function measureLine(path){

   var res = new Array;

   var lineStart = path.subPathItems[0].pathPoints[0].anchor;

   var lineEnd = path.subPathItems[0].pathPoints[1].anchor;

   var a = Math.max(lineStart[0],lineEnd[0])-Math.min(lineStart[0],lineEnd[0]);

   var o = Math.max(lineStart[1],lineEnd[1])-Math.min(lineStart[1],lineEnd[1]);

   var c = Math.round(Math.sqrt((a*a)+(o*o)));

   res.push(c);

   var ang = (180/Math.PI) * Math.atan2(o,a);

   if(lineStart[1] < lineEnd[1]){//negative angle

      ang = -ang;

   };

   res.push(ang);

   return res;

   }

JJMack
Community Expert
Community Expert
November 24, 2011

I would think that if the measure tool were recordable which it is not you would need to set the two end points.  If you have the two end points you do not need the measure tool for its then simple math the length is the square root of the sum of the width length squared and the height length squared.

With the line tool set to create a path you could daw a line path and have  a script to get the bounds of the path or path turned into a selection and do the above math. To automate the process you could record an interactine action to create the line path then have the action use the script that calulayes the line length after the interactive path step..

JJMack
Inspiring
November 24, 2011

JJMack,

I have never been able to find a way that allows the user to make the path using the line tool while the script is running. I will admit I never thought of actions but I can't get it it work with actions either. Can you post the steps to create an interactive action using the line tool?

Inspiring
November 25, 2011

It should work correctly after all it just a right triangle. You know Pythagorean theorem - The sum of the areas of the two squares on the legs (a and b) equals the area of the square on the hypotenuse (c).  Try adding a delet Work Path step at the beginning of the action so yoy cam play it over and over. And use this script with the trialgle spelled out for as an alert.

// enable double-clicking from Mac Finder or Windows Explorer

#target photoshop // this command only works in Photoshop CS2 and higher

// bring application forward for double-click events

app.bringToFront();

// ensure at least one document open

if (!documents.length) alert('There are no documents open.', 'No Document');

else {

          main(); // at least one document exists proceed

}

///////////////////////////////////////////////////////////////////////////////

//                            main function                                  //

///////////////////////////////////////////////////////////////////////////////

function main() {

          // declare local variables

          var orig_ruler_units = app.preferences.rulerUnits;

          app.preferences.rulerUnits = Units.PIXELS;          // Set the ruler units to PIXELS

          try { alert(measureLine(app.activeDocument.pathItems.getByName("Work Path"))); }

          // display error message if something goes wrong

          catch(e) { alert(e + ': on line ' + e.line, 'Script Error', true); }

          app.preferences.rulerUnits = orig_ruler_units;          // Reset units to original settings

}

///////////////////////////////////////////////////////////////////////////////

//                           main function end                               //

///////////////////////////////////////////////////////////////////////////////

//the code below is for the Line tool.

function measureLine(path){

          var res = new Array;

          var lineStart = path.subPathItems[0].pathPoints[0].anchor;

          var lineEnd = path.subPathItems[0].pathPoints[3].anchor;

          var a = Math.max(lineStart[0],lineEnd[0])-Math.min(lineStart[0],lineEnd[0]);

          var o = Math.max(lineStart[1],lineEnd[1])-Math.min(lineStart[1],lineEnd[1]);

          var c = Math.round(Math.sqrt((a*a)+(o*o)));

          alert("Triangle Height = " + o + " Width = " + a + " Hypotenuse = " + c );

          res.push(c);

          var ang = (180/Math.PI) * Math.atan2(o,a);

          if(lineStart[1] < lineEnd[1]){//negative angle

                    ang = -ang;

          };

          res.push(ang);

          return res;

}


Sorry if these points are obvious to you but they have tripped up other users.

Make sure the line tool is not using arrowheads.

The path needs to be made from left to right.

Right-left directon and Arrowheads change  the path points of the line. Arrowheads adds points so the script reads the head instead to the shaft. Right to left changes the order of the points so that the line weight effects the angle.