26 Replies Latest reply on Feb 16, 2012 7:18 AM by c.pfaffenbichler

    Where to Start?

    NOAA-mlynn

      Using CS5 Extended.  I want to be able to designate a line (maybe with line drawing or measurement tool?) and have the program automatically draw perpendicular lines at the 10, 20, 30, 40, 50, 60, 70, 80 and 90 percent distances along that line.  Have no idea where to start looking for a solution to this.  Can anybody suggest anything?  Thanks

        • 1. Re: Where to Start?
          Curt Y Level 7

          Have no direct solultion, but when you get into percentage spacing, rather than pixel or dimension spacing you add complexity.

           

          To get a percentage you have to know the horizontal width and then divide that up into 9 pieces.  Not sure how this is done in PS automatically.

           

          You could do it on paper and draw the lines based on the ruler.  But if you have lots of images it would be very time intensive.

          • 3. Re: Where to Start?
            NOAA-mlynn Level 1

            Thanks, that might help, I will look.  I was given a script that does what I want that works in Media Cybernetics' Image-Pro.  I'll have to see if it can be adapted to work in Photoshop.

            • 4. Re: Where to Start?
              c.pfaffenbichler Level 8

              Personally I would prefer creating a two-point-path with the Pen Tool.

              How long and thick are the perpendicular lines supposed to be?

              • 5. Re: Where to Start?
                Trevor.Dennis Adobe Community Professional (Moderator)

                I don't know how much automation you are trying to achieve, and I don't do scripts, but here is something you might work into an action, or it would at least streamline a manual workflow.

                 

                • Turn on the grid, and make sure Snap to grid is turned on
                • Draw your long line, and align the ends with grid intersections.  I just did this using the Line tool, and immediately Rasterizing it.
                • Draw the first of your perpendicular lines.  This is where Snap-to-grid is going to be helpful.  (I used the same Rasterized Shape tool to do this)
                • Copy the perpendicular line ten times.  (Keep hitting Ctrl j until you reach *** copy 10)
                • Move the top most perpendicular layer to the far end of the long line. (snap-to-grid is still your friend)
                • Select the Move tool. Select all eleven perpendicular lines, and click Distribute right edges from the Options bar (it's the second button from the end on the right.

                 

                AFAICT this is going to do what you ask, but I am not sure how you would incorperate some of those steps into an Action.  Maybe if you made the line the full width of the canvas, and transform the end result to the required size.  It took me less than a minute to test it manually.

                • 6. Re: Where to Start?
                  NOAA-mlynn Level 1

                  I will try those ideas as well.  Actually it's not the lines themselves I'm interested in.  What I am doing is looking at vertical images taken of whales.  We look at the health of a whale (condition index) based on it's measurements. Total Length and Fluke width are simple and straight forward.  But our technique depends measuring the width of the whale at 10% increments of it's length.  So the lines are really only marking where to measure.  There are lots of animals to measure, so I'd like to not spend a lot time getting the increments for each whale.  The script for image-pro works fine, you draw a line, run the script, and short lines pop up perpendicular to it at the increments.  Since I do all my other work with Photoshop, it's just a pain to import the images to another program just for this one thing, (not to mention it's an expensive program to use for this one thing), so I was hoping I could get Photoshop to do it as well!

                  • 7. Re: Where to Start?
                    c.pfaffenbichler Level 8

                    Seems I had misunderstood … just to make sure, could you please post an image of the original line and the resulting lines you want?

                    • 8. Re: Where to Start?
                      PECourtejoie Adobe Community Professional

                      Hello!

                      I think that you should create a vector shape, that you could lay on top of the whales to measure them.

                      But I'd also ike to see an example to better help you.

                      • 9. Re: Where to Start?
                        arc fixer Level 3

                        Hi.

                         

                        What PJ said.

                         

                        WHALE.JPG

                         

                        Save the grid as a Custom Shape. Then use the Shape Tool to drag it to the whale. The dividers will scale.

                         

                        I'm sure you know that Ps Extended will record the ruler measurements along with setting the scale conversion.

                         

                        FWIW.

                         

                        Peace,

                        Lee

                        1 person found this helpful
                        • 10. Re: Where to Start?
                          NOAA-mlynn Level 1

                          I'm going to experiment with the custom shape grid.  From the pic, it looks like it may do the trick as long as I can adust the endpoints to where I want them with the other lines maintaining their relative positions.  It looks pretty much like what I got from the Image-Pro script (see pic)

                           

                          Final Blue with crosshatches (small).jpg

                           

                          I draw the original measurement (red) line, run the scrip and the yellow lines pop up along it.  Although the script puts in the actual % labels, that isn't really needed.  I just use the lines to measure the whale width at that point.  The nice part is that it doesn't matter what the orientation of the animal is, the cross-hatches are always perpendicular to the original line.

                           

                          Thanks for all the ideas!

                          • 11. Re: Where to Start?
                            c.pfaffenbichler Level 8

                            The distances that script produces look a bit irregular.

                            Anyway, I’m confident a similar result can be achieved with JavaScript in Photoshop if the Custom Shape should not live up to your expectations.

                            • 12. Re: Where to Start?
                              PECourtejoie Adobe Community Professional

                              PJ? Is that me?

                              • 13. Re: Where to Start?
                                PECourtejoie Adobe Community Professional

                                NOAA, it seems that the script does not create equidistant lines!

                                Lee has made what I had in mind:

                                To recreate one,

                                Create a square file.

                                Put guides every 10% (ctrl+R to show Rulers, then right-click in them to change the unit.)

                                Now you can use the Line tool set to vector shape mode and in add shapes mode, and drag an horizontal line, then vertical ones.

                                You might even add text if it makes reading easier, just right-click on their layer to convert it to shape, that you'll be able to merge with your "hand made ruler"

                                Once all the shapes are on the same layer, go to Edit>Define Custom Shape to save it (as an additional step, do save the set to your hard drive.)

                                You'll then be able to add the shape, and rotate it at will to measure the whales.

                                • 14. Re: Where to Start?
                                  arc fixer Level 3

                                  Sorry, PE. Senior moment. 

                                  • 15. Re: Where to Start?
                                    NOAA-mlynn Level 1

                                    Yeah, something happened in the translation to posting.  In the original, the lines are equidistant.

                                    • 16. Re: Where to Start?
                                      NOAA-mlynn Level 1

                                      Well, I think I'm going to call this one solved!  See pic. There is a little extra work involved in rotating and sizing the "ruler" shape to the whale. But unless I can get a scripting to do it all automatically when I do a length measure line, I don't think it can get any easier.

                                      Blue with Photoshop cross hatches-sm.jpg

                                       

                                      My thanks to all who replyed, and special thanks to Lee and PE for getting me there!

                                      -Morgan Lynn

                                      • 17. Re: Where to Start?
                                        c.pfaffenbichler Level 8

                                        Could you give this a try – it creates a Path based on the Ruler, maybe that suffices.

                                        And the Script could be triggered via Keyboard Shortcut or from a Configurator Panel.

                                         

                                        Edited:

                                        // create perpendicular lines to the ruler as created with the ruler tool; requires CS5;
                                        // thanks to david and mike hale;;
                                        // 2012, use it at your own risk;
                                        #target photoshop
                                        if (app.documents.length > 0) {
                                        // define the percentage steps;
                                        var theSteps = 10;
                                        var myDocument = app.activeDocument;
                                        // set to points;
                                        var origRes = myDocument.resolution;
                                        var originalRulerUnits = app.preferences.rulerUnits;
                                        app.preferences.rulerUnits = Units.POINTS;
                                        // get ruler tool points;
                                        var thePoints = getRulerEndpoints();
                                        if (thePoints.length > 0) {
                                        // get measurements;
                                        var theLength = getDistance(thePoints[0], thePoints[1]);
                                        var theAngle = getAngle(thePoints[0], thePoints[1]);
                                        // create the array of points;
                                        var theArray = [[[thePoints[0]], [thePoints[1]], false, ShapeOperation.SHAPEADD]];
                                        // get new lines;
                                        for (var m = 0; m < theSteps + 1; m++) {
                                                  var theCenter = [thePoints[0][0] + (theLength[1] / theSteps * m), thePoints[0][1] + (theLength[2] / theSteps * m)];
                                                  var theHor = theCenter[0] + (Math.cos(radiansOf(theAngle + 90)) * theLength[0] / 2);
                                                  var theVer = theCenter[1] + (Math.sin(radiansOf(theAngle + 90)) * theLength[0] / 2);
                                                  var point1 = [theHor, theVer];
                                                  var theHor2 = theCenter[0] + (Math.cos(radiansOf(theAngle - 90)) * theLength[0] / 2);
                                                  var theVer2 = theCenter[1] + (Math.sin(radiansOf(theAngle - 90)) * theLength[0] / 2);
                                                  var point2 = [theHor2, theVer2]; 
                                                  theNewArray = [[point1], [point2], false, ShapeOperation.SHAPEADD];
                                                  theArray.push(theNewArray)
                                                  };
                                        // create path;
                                        var thePath = createPath (theArray, dateString(), origRes);
                                        };
                                        // reset;
                                        app.preferences.rulerUnits = originalRulerUnits;
                                        };
                                        ////////////////////////////////////
                                        ////// get ruler tool end points //////
                                        // from http://ps-scripts.com/bb/viewtopic.php?f=2&t=3817
                                        // by david and mike hale;
                                        function getRulerEndpoints(){
                                           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 result = executeAction( charIDToTypeID('getd'), desc, DialogModes.NO );
                                           if  (result.hasKey( charIDToTypeID('Pts ') )){
                                              var i, ptList = result.getList( charIDToTypeID('Pts ') );
                                              // The middle item in the list is an unused "midpoint" (currently == p0)
                                              var p0 = getUnitPoint( ptList.getObjectValue(0) );
                                              var p1 = getUnitPoint( ptList.getObjectValue(2) );
                                              if (p0.fX < p1.fX)
                                                 return [p0, p1];
                                              else
                                                 return [p1, p0];
                                           }
                                           else
                                              return [];
                                        };
                                        function getUnitPoint(desc){
                                           var x = desc.getUnitDoubleValue( charIDToTypeID('X   ') );
                                           var y = desc.getUnitDoubleValue( charIDToTypeID('Y   ') );
                                           function TPoint( x, y ){
                                              this.fX = x;
                                              this.fY = y;
                                           }
                                        //   return new TPoint( x, y );
                                           return ( [x, y] );
                                        };
                                        //////
                                        ////// function to get the date //////
                                        function dateString () {
                                                  var now = new Date();
                                                  var day = now.getDate();
                                                  day = bufferNumberWithZeros(day, 2);
                                                  var month = now.getMonth();
                                                  month++;
                                                  month = bufferNumberWithZeros(month, 2);
                                                  var year = now.getFullYear();
                                                  var hour = now.getHours();
                                                  hour = bufferNumberWithZeros(hour, 2);
                                                  var minutes = now.getMinutes();
                                                  minutes = bufferNumberWithZeros(minutes, 2);
                                                  var seconds = now.getSeconds();
                                                  seconds = bufferNumberWithZeros(seconds, 2);
                                                  var myDateText = year+"-"+month+"-"+day+"_"+hour+"-"+minutes+"-"+seconds;
                                                  return myDateText
                                                  };
                                        ////// buffer number with zeros //////
                                        function bufferNumberWithZeros (number, places) {
                                                  var theNumberString = String(number);
                                                  for (var o = 0; o < (places - String(number).length); o++) {
                                                            theNumberString = String("0" + theNumberString)
                                                            };
                                                  return theNumberString
                                                  };
                                        ////// function to create path from array with one array per point that holds anchor, leftdirection, etc, 2010 //////
                                        function createPath (theArray, thePathsName, res) {
                                        var originalRulerUnits = app.preferences.rulerUnits;
                                        app.preferences.rulerUnits = Units.POINTS;
                                        lineSubPathArray = new Array ();
                                        if (theArray[theArray.length - 1].constructor != Array) {var numberOfSubPathItems = theArray.length - 1}
                                        else {var numberOfSubPathItems = theArray.length};
                                        for (var b = 0; b < numberOfSubPathItems; b++) {
                                                  var lineArray = new Array ();
                                                  for (c = 0; c < (theArray[b].length - 2); c++) {
                                                            lineArray[c] = new PathPointInfo;
                                                            if (!theArray[b][c][3]) {lineArray[c].kind = PointKind.CORNERPOINT}
                                                            else {lineArray[c].kind = theArray[b][c][3]};
                                                            lineArray[c].anchor = [theArray[b][c][0][0] * 72 / res, theArray[b][c][0][1] * 72 / res];
                                        //                    lineArray[c].anchor = theArray[b][c][0];
                                                            if (!theArray[b][c][1]) {lineArray[c].leftDirection = lineArray[c].anchor}
                                                            else {lineArray[c].leftDirection = theArray[b][c][1]};
                                                            if (!theArray[b][c][2]) {lineArray[c].rightDirection = lineArray[c].anchor}
                                                            else {lineArray[c].rightDirection = theArray[b][c][2]}; 
                                                            };
                                                  lineSubPathArray[b] = new SubPathInfo();
                                                  lineSubPathArray[b].closed = theArray[b][theArray[b].length - 2];
                                                  lineSubPathArray[b].operation = theArray[b][theArray[b].length - 1];
                                                  lineSubPathArray[b].entireSubPath = lineArray;
                                                  };
                                        var myPathItem = app.activeDocument.pathItems.add(thePathsName, lineSubPathArray);
                                        app.preferences.rulerUnits = originalRulerUnits;
                                        return myPathItem
                                        };
                                        ////// radians //////
                                        function radiansOf (theAngle) {
                                                  return theAngle * Math.PI / 180
                                                  };
                                        ////// get an angle, 3:00 being 0˚, 6:00 90˚, etc. //////
                                        function getAngle (pointOne, pointTwo) {
                                        // calculate the triangle sides;
                                                  var width = pointTwo[0] - pointOne[0];
                                                  var height = pointTwo[1] - pointOne[1];
                                                  var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)); 
                                        // calculate the angles;
                                                  if (width+width > width) {theAngle = Math.asin(height / sideC) * 360 / 2 / Math.PI}
                                                  else {theAngle = 180 - (Math.asin(height / sideC) * 360 / 2 / Math.PI)};
                                                  if (theAngle < 0) {theAngle = (360 + theAngle)};
                                        //          if (theAngle > 180) {theAngle = (360 - theAngle) * (-1)};
                                                  return theAngle
                                                  };
                                        ////// get a distance between two points , retirn array with distance and ho and ver dist //////
                                        function getDistance (pointOne, pointTwo) {
                                        // calculate the triangle sides;
                                                  var width = pointTwo[0] - pointOne[0];
                                                  var height = pointTwo[1] - pointOne[1];
                                                  var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)); 
                                                  return [sideC, width, height]
                                        //          return sideC
                                                  };
                                        
                                        
                                        
                                        • 18. Re: Where to Start?
                                          PECourtejoie Adobe Community Professional

                                          I feel better, knowing that our Photoshop knowledge is remotely useful to the protection and survival of the whales!

                                          It looks like there is a smaller whale (baby?) below that one. How cute!

                                           

                                          Edit: I knew a script was coming. Sure wish I could get my head around scripting!

                                          • 19. Re: Where to Start?
                                            NOAA-mlynn Level 1

                                            Thanks for the script.  It definitely gives me something to work with.  At first run it puts a smaller crosshatch pattern offset to the upper left corner of my image, in same orientation but not along the line of the ruler tool.  I'm not familiar with java script or using them.  I just copy/pasted the script into text editor (windows notepad) and saved as Unicode and as a .js file.  This may have something to do with why it doesn't work right?  It's amazing what you start learning when you start off with a question about how to do something!  Like PE, now I'm going to have to get my head around scripting....

                                             

                                            And yes, there was a baby (a calf) with that Blue Whale mom (cow).  Photo taken around the Channel Islands off the coast of Southern California.

                                            • 20. Re: Where to Start?
                                              c.pfaffenbichler Level 8

                                              No, sorry, that was my fault – I initially tested on 72ppi files therefore I could disregard the resolution.

                                              I subsequently updated the Script, in its current form it should work better.

                                               

                                              Paste the text into a new file in ExtendScript Toolkit (part of Photoshop’s installation, /Applications/Utilities/Adobe Utilities-CS5/ExtendScript Toolkit CS5) and save it as a jsx-file into Photoshop’s Presets/Scripts-folder.

                                              After restarting Photoshop the Script should be available under File > Scripts and can be assigned a Keyboard Shortcut directly, recorded into an Action, be used in a Configurator-Panel or started from ExtendScript Toolkit directly.

                                              1 person found this helpful
                                              • 21. Re: Where to Start?
                                                NOAA-mlynn Level 1

                                                That works perfectly.  Thanks so much!  Now I can use the ruler, hit a function key and presto!  And now have a new toy to play with (the ESTK).

                                                I'm new to forums of any kind, and I must say I'm impressed, I never expected anyone to actually procure an actual script for me, just tell me it could be done.

                                                 

                                                You know, I do like learning and exploring, but I'm also lazy, so I'll ask this one rather than experiment on my own...do you know of a way to make the ruler tool lay down an actual line that stays on the image?

                                                • 22. Re: Where to Start?
                                                  PECourtejoie Adobe Community Professional

                                                  Christoph, did you code every line, or did the script listener intervene at some point?

                                                  • 23. Re: Where to Start?
                                                    c.pfaffenbichler Level 8

                                                    Christoph, did you code every line, or did the script listener intervene at some point?

                                                    Most of it is Dosument Object Model-based, so I did not have to use ScriptingListener – but the function to evaluate the Ruler’s endpoint I have found on ps-scripts.com (by David and edited by Mike Hale) and it uses ActionDescriptor-code in a way that I would probably not have been able to figure out myself.

                                                    • 24. Re: Where to Start?
                                                      c.pfaffenbichler Level 8

                                                      do you know of a way to make the ruler tool lay down an actual line that stays on the image?

                                                      That can be done; do you want an extra layer or a flattened image as the result? 

                                                      • 25. Re: Where to Start?
                                                        NOAA-mlynn Level 1

                                                        I would say in a layer, I can always flatten the image later for display/sharing purposes.  Unless the other way involves a lot less steps.

                                                        • 26. Re: Where to Start?
                                                          c.pfaffenbichler Level 8

                                                          Try this.

                                                          The text layers take a lot of time, if you don’t need them, just delete the line (or type two slashes in front of it)

                                                                    var aTextLayer = createTextLayer (String(m * 100 / theSteps)+"%", point1, origRes);
                                                          

                                                           

                                                          Otherwise this might work.

                                                          // create perpendicular lines to the ruler as created with the ruler tool; requires CS5;
                                                          // thanks to david and mike hale;;
                                                          // 2012, use it at your own risk;
                                                          #target photoshop
                                                          if (app.documents.length > 0) {
                                                          // define the percentage steps;
                                                          var theSteps = 10;
                                                          var myDocument = app.activeDocument;
                                                          // set to points;
                                                          var origRes = myDocument.resolution;
                                                          var originalRulerUnits = app.preferences.rulerUnits;
                                                          app.preferences.rulerUnits = Units.POINTS;
                                                          // get ruler tool points;
                                                          var thePoints = getRulerEndpoints();
                                                          if (thePoints.length > 0) {
                                                          // get measurements;
                                                          var theLength = getDistance(thePoints[0], thePoints[1]);
                                                          var theAngle = getAngle(thePoints[0], thePoints[1]);
                                                          // create the array of points;
                                                          var theArray = [[[thePoints[0]], [thePoints[1]], false, ShapeOperation.SHAPEADD]];
                                                          var theTextLayers = new Array;
                                                          // get new lines;
                                                          for (var m = 0; m < theSteps + 1; m++) {
                                                                    var theCenter = [thePoints[0][0] + (theLength[1] / theSteps * m), thePoints[0][1] + (theLength[2] / theSteps * m)];
                                                                    var theHor = theCenter[0] + (Math.cos(radiansOf(theAngle + 90)) * theLength[0] / 4);
                                                                    var theVer = theCenter[1] + (Math.sin(radiansOf(theAngle + 90)) * theLength[0] / 4);
                                                                    var point1 = [theHor, theVer];
                                                                    var theHor2 = theCenter[0] + (Math.cos(radiansOf(theAngle - 90)) * theLength[0] / 4);
                                                                    var theVer2 = theCenter[1] + (Math.sin(radiansOf(theAngle - 90)) * theLength[0] / 4);
                                                                    var point2 = [theHor2, theVer2]; 
                                                                    theNewArray = [[point1], [point2], false, ShapeOperation.SHAPEADD];
                                                                    theArray.push(theNewArray);
                                                          // create text;
                                                                    var aTextLayer = createTextLayer (String(m * 100 / theSteps)+"%", point1, origRes);
                                                                    try {theTextLayers.push(aTextLayer)}
                                                                    catch (e) {}
                                                                    };
                                                          // create path;
                                                          var thePath = createPath (theArray, dateString(), origRes);
                                                          // set foreground color;
                                                          app.foregroundColor.rgb.red = 255;
                                                          app.foregroundColor.rgb.green = 0;
                                                          app.foregroundColor.rgb.blue = 0;
                                                          var theLayer = myDocument.artLayers.add();
                                                          // set pen tool to 2 pixels;
                                                          // =======================================================
                                                          var idslct = charIDToTypeID( "slct" );
                                                              var desc3 = new ActionDescriptor();
                                                              var idnull = charIDToTypeID( "null" );
                                                                  var ref2 = new ActionReference();
                                                                  var idPcTl = charIDToTypeID( "PcTl" );
                                                                  ref2.putClass( idPcTl );
                                                              desc3.putReference( idnull, ref2 );
                                                          executeAction( idslct, desc3, DialogModes.NO );
                                                          // =======================================================
                                                          var idsetd = charIDToTypeID( "setd" );
                                                              var desc2 = new ActionDescriptor();
                                                              var idnull = charIDToTypeID( "null" );
                                                                  var ref1 = new ActionReference();
                                                                  var idBrsh = charIDToTypeID( "Brsh" );
                                                                  var idOrdn = charIDToTypeID( "Ordn" );
                                                                  var idTrgt = charIDToTypeID( "Trgt" );
                                                                  ref1.putEnumerated( idBrsh, idOrdn, idTrgt );
                                                              desc2.putReference( idnull, ref1 );
                                                              var idT = charIDToTypeID( "T   " );
                                                                  var desc3 = new ActionDescriptor();
                                                                  var idmasterDiameter = stringIDToTypeID( "masterDiameter" );
                                                                  var idPxl = charIDToTypeID( "#Pxl" );
                                                                  desc3.putUnitDouble( idmasterDiameter, idPxl, 2.000000 );
                                                              var idBrsh = charIDToTypeID( "Brsh" );
                                                              desc2.putObject( idT, idBrsh, desc3 );
                                                          executeAction( idsetd, desc2, DialogModes.NO );
                                                          // stroke path;
                                                          myDocument.pathItems[myDocument.pathItems.length - 1].strokePath(ToolType.PENCIL, false);
                                                          // flatten layers;
                                                          for (var n = 0; n < theTextLayers.length; n++) {theLayer = theLayer.merge()}
                                                          };
                                                          // reset;
                                                          app.preferences.rulerUnits = originalRulerUnits;
                                                          };
                                                          ////////////////////////////////////
                                                          ////// get ruler tool end points //////
                                                          // from http://ps-scripts.com/bb/viewtopic.php?f=2&t=3817
                                                          // by david and mike hale;
                                                          function getRulerEndpoints(){
                                                             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 result = executeAction( charIDToTypeID('getd'), desc, DialogModes.NO );
                                                             if  (result.hasKey( charIDToTypeID('Pts ') )){
                                                                var i, ptList = result.getList( charIDToTypeID('Pts ') );
                                                                // The middle item in the list is an unused "midpoint" (currently == p0)
                                                                var p0 = getUnitPoint( ptList.getObjectValue(0) );
                                                                var p1 = getUnitPoint( ptList.getObjectValue(2) );
                                                                if (p0.fX < p1.fX)
                                                                   return [p0, p1];
                                                                else
                                                                   return [p1, p0];
                                                             }
                                                             else
                                                                return [];
                                                          };
                                                          function getUnitPoint(desc){
                                                             var x = desc.getUnitDoubleValue( charIDToTypeID('X   ') );
                                                             var y = desc.getUnitDoubleValue( charIDToTypeID('Y   ') );
                                                             function TPoint( x, y ){
                                                                this.fX = x;
                                                                this.fY = y;
                                                             }
                                                          //   return new TPoint( x, y );
                                                             return ( [x, y] );
                                                          };
                                                          ////// function to get the date //////
                                                          function dateString () {
                                                                    var now = new Date();
                                                                    var day = now.getDate();
                                                                    day = bufferNumberWithZeros(day, 2);
                                                                    var month = now.getMonth();
                                                                    month++;
                                                                    month = bufferNumberWithZeros(month, 2);
                                                                    var year = now.getFullYear();
                                                                    var hour = now.getHours();
                                                                    hour = bufferNumberWithZeros(hour, 2);
                                                                    var minutes = now.getMinutes();
                                                                    minutes = bufferNumberWithZeros(minutes, 2);
                                                                    var seconds = now.getSeconds();
                                                                    seconds = bufferNumberWithZeros(seconds, 2);
                                                                    var myDateText = year+"-"+month+"-"+day+"_"+hour+"-"+minutes+"-"+seconds;
                                                                    return myDateText
                                                                    };
                                                          ////// buffer number with zeros //////
                                                          function bufferNumberWithZeros (number, places) {
                                                                    var theNumberString = String(number);
                                                                    for (var o = 0; o < (places - String(number).length); o++) {
                                                                              theNumberString = String("0" + theNumberString)
                                                                              };
                                                                    return theNumberString
                                                                    };
                                                          ////// function to create path from array with one array per point that holds anchor, leftdirection, etc, 2010 //////
                                                          function createPath (theArray, thePathsName, res) {
                                                          if (!res) {var res = 72};
                                                          var originalRulerUnits = app.preferences.rulerUnits;
                                                          app.preferences.rulerUnits = Units.POINTS;
                                                          lineSubPathArray = new Array ();
                                                          if (theArray[theArray.length - 1].constructor != Array) {var numberOfSubPathItems = theArray.length - 1}
                                                          else {var numberOfSubPathItems = theArray.length};
                                                          for (var b = 0; b < numberOfSubPathItems; b++) {
                                                                    var lineArray = new Array ();
                                                                    for (c = 0; c < (theArray[b].length - 2); c++) {
                                                                              lineArray[c] = new PathPointInfo;
                                                                              if (!theArray[b][c][3]) {lineArray[c].kind = PointKind.CORNERPOINT}
                                                                              else {lineArray[c].kind = theArray[b][c][3]};
                                                                              lineArray[c].anchor = [theArray[b][c][0][0] * 72 / res, theArray[b][c][0][1] * 72 / res];
                                                          //                    lineArray[c].anchor = theArray[b][c][0];
                                                                              if (!theArray[b][c][1]) {lineArray[c].leftDirection = lineArray[c].anchor}
                                                                              else {lineArray[c].leftDirection = theArray[b][c][1]};
                                                                              if (!theArray[b][c][2]) {lineArray[c].rightDirection = lineArray[c].anchor}
                                                                              else {lineArray[c].rightDirection = theArray[b][c][2]}; 
                                                                              };
                                                                    lineSubPathArray[b] = new SubPathInfo();
                                                                    lineSubPathArray[b].closed = theArray[b][theArray[b].length - 2];
                                                                    lineSubPathArray[b].operation = theArray[b][theArray[b].length - 1];
                                                                    lineSubPathArray[b].entireSubPath = lineArray;
                                                                    };
                                                          var myPathItem = app.activeDocument.pathItems.add(thePathsName, lineSubPathArray);
                                                          app.preferences.rulerUnits = originalRulerUnits;
                                                          return myPathItem
                                                          };
                                                          ////// radians //////
                                                          function radiansOf (theAngle) {
                                                                    return theAngle * Math.PI / 180
                                                                    };
                                                          ////// get an angle, 3:00 being 0˚, 6:00 90˚, etc. //////
                                                          function getAngle (pointOne, pointTwo) {
                                                          // calculate the triangle sides;
                                                                    var width = pointTwo[0] - pointOne[0];
                                                                    var height = pointTwo[1] - pointOne[1];
                                                                    var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)); 
                                                          // calculate the angles;
                                                                    if (width+width > width) {theAngle = Math.asin(height / sideC) * 360 / 2 / Math.PI}
                                                                    else {theAngle = 180 - (Math.asin(height / sideC) * 360 / 2 / Math.PI)};
                                                                    if (theAngle < 0) {theAngle = (360 + theAngle)};
                                                          //          if (theAngle > 180) {theAngle = (360 - theAngle) * (-1)};
                                                                    return theAngle
                                                                    };
                                                          ////// get a distance between two points , retirn array with distance and ho and ver dist //////
                                                          function getDistance (pointOne, pointTwo) {
                                                          // calculate the triangle sides;
                                                                    var width = pointTwo[0] - pointOne[0];
                                                                    var height = pointTwo[1] - pointOne[1];
                                                                    var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)); 
                                                                    return [sideC, width, height]
                                                          //          return sideC
                                                                    };
                                                          ////// add text layer //////
                                                          function createTextLayer (thisText, thePoint, res) {
                                                          var docRef = activeDocument;
                                                          var myLayerRef = docRef.artLayers.add();
                                                          myLayerRef.kind = LayerKind.TEXT;
                                                          myLayerRef.name = thisText;
                                                          var myTextRef = myLayerRef.textItem;
                                                          myTextRef.kind = TextType.POINTTEXT;
                                                          myTextRef.size = 12 * 72 / res;
                                                          myTextRef.font = "Arial";
                                                          //Set text colour in RGB values
                                                          var newColor = new SolidColor();
                                                          newColor.rgb.red = 0;
                                                          newColor.rgb.green = 0;
                                                          newColor.rgb.blue = 0;
                                                          myTextRef.color = newColor;
                                                          // set the position;
                                                          myTextRef.position = [thePoint[0] * 72 / res, thePoint[1] * 72 / res];
                                                          myLayerRef.blendMode = BlendMode.NORMAL;
                                                          myLayerRef.opacity = 100;
                                                          myTextRef.useAutoLeading = false;
                                                          myTextRef.leading = 0; 
                                                          myTextRef.contents = thisText;
                                                          // rasterize layer;
                                                          docRef.activeLayer.rasterize(RasterizeType.TEXTCONTENTS);
                                                          return docRef.activeLayer
                                                          };