Skip to main content
Known Participant
August 26, 2017
Answered

Changine Line Weight after a line has already been drawn

  • August 26, 2017
  • 6 replies
  • 44285 views

Hi,

I am using Photoshop Release 2017.1.1.  Let's say I use the Line Tool to draw a Line with a Stroke Width of 10 px and a Line Weight of 100 px.  After drawing this Line, I leave it selected.  Then I change the Line Weight setting to 200 px.  This does not change the Line Weight of the existing Line I already drew, but if I draw a new Line, the new Line has the thicker Line Weight (200 px).

Now I would like to change the Line Weight of the first Line.  As long as I select the Layer that this Line is on, I can select the Line with either the Direct Selection Tool or the Path Selection Tool.  Whichever Selection Tool I use, I am able to change the Stroke Width by changing the value where I have circled in Blue below...

... but I cannot figure out how to change the Line Weight.  If anyone can give me a clue, I would greatly appreciate it.

Thanks in advance,
Paul

This topic has been closed for replies.
Correct answer Chuck Uebele

Here is a script that will change the line width and size of arrowheads. It will not change a line into an arrow or an arrow into a line.

#target photoshop

//copyright 2017 Chuck Uebele, all rights reserved

//Use at your own risk.

var xmlFile = new File(Folder.desktop+'/ArrowPrefs.xml');

var xmlPref

if(xmlFile.exists){

    xmlPref = readXMLFile (xmlFile)

    //alert(xmlPref.prefs.lines.children().length())

    //alert(xmlPref.prefs.lines.children()[0].@preset)

    }

else{xmlPref = new XML('<root><prefs><lines/><arrows/></prefs>')};

//varables for lines and points

var run = true;

var lineType;

var origLineWidth;

var lineAngTan1;//from first point to oppsite side of line

var lineAngTan2;//From oppsite side of line to first point

var lineLengthAng;

var lineLength;

var lineMid1;//mid width on line from first point

var lineMid2;//mid width on line from oppsite end of line

var newWidth = 20

var ptTemp1

var ptTemp2

var ptTemp3

var ptTemp4

var dropLst = new Array()

var prefsDrop

var headIntersect1;

var headIntersect2;

//-----------

var arrowLength;

var arrowWidth;

var arrowEndsMid;

var arrowConcave;

var arrowConcaveFactor;

var arrowLengthFactor;

var arrowWidthFactor;

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

app.preferences.rulerUnits = Units.PIXELS;

try{

    var doc = activeDocument

    var sLay = doc.activeLayer

    var sLayName = sLay.name + ' Shape Path'

    var cPath = doc.pathItems.getByName(sLayName)

    var ptArray = new Array();

    var ptNewArray = new Array();

    var idPath;

//var numAnchors = cPath.subPathItems[0].pathPoints.length;

recordAnchors (cPath);

var numAnchors = ptArray.length;

    }

catch(e){

    run = false;

    var numAnchors=0

    }

switch(numAnchors){

    case 4:

        lineType = 'Normal Line'

        origLineWidth = lineL (ptArray[0][0], ptArray[0][1], ptArray[1][0], ptArray[1][1]);

        lineAngTan1 = getAng (ptArray[0][0], ptArray[0][1], ptArray[1][0], ptArray[1][1]);

        lineAngTan2 = getAng (ptArray[1][0], ptArray[1][1], ptArray[0][0], ptArray[0][1]);

        lineMid1 = [(ptArray[0][0] + ptArray[1][0])/2,(ptArray[0][1] + ptArray[1][1])/2 ]; 

        lineMid2 = [(ptArray[2][0] + ptArray[3][0])/2,(ptArray[2][1] + ptArray[3][1])/2 ];

       

        ui ();

       

        ptNewArray[0] = newPt (lineMid1[0],lineMid1[1], newWidth/2, lineAngTan1);

        ptNewArray[3] = newPt (lineMid2[0],lineMid2[1], newWidth/2, lineAngTan1);

        ptNewArray[1] = newPt (lineMid1[0],lineMid1[1], newWidth/2, lineAngTan2);

        ptNewArray[2] = newPt (lineMid2[0],lineMid2[1], newWidth/2, lineAngTan2);

        break;

    case 7:

        if(Math.round (getAng (ptArray[0][0], ptArray[0][1], ptArray[6][0], ptArray[6][1]))==Math.round (getAng (ptArray[1][0], ptArray[1][1], ptArray[2][0], ptArray[2][1]))){

            //alert('end')

            lineType = 'Single Arrow End';

            origLineWidth = lineL (ptArray[0][0], ptArray[0][1], ptArray[1][0], ptArray[1][1]);

            lineAngTan1 = getAng (ptArray[0][0], ptArray[0][1], ptArray[1][0], ptArray[1][1]);

            lineAngTan2 = getAng (ptArray[1][0], ptArray[1][1], ptArray[0][0], ptArray[0][1]);

            lineMid1 = [(ptArray[1][0] + ptArray[0][0])/2,(ptArray[1][1] + ptArray[0][1])/2 ]; 

            lineMid2 = [(ptArray[2][0] + ptArray[6][0])/2,(ptArray[2][1] + ptArray[6][1])/2 ];

            arrowEndsMid = [(ptArray[3][0] + ptArray[5][0])/2,(ptArray[3][1] + ptArray[5][1])/2 ];           

            arrowLength = lineL (ptArray[4][0], ptArray[4][1], arrowEndsMid[0], arrowEndsMid[1]);             

            arrowWidth = lineL (ptArray[5][0], ptArray[5][1], ptArray[3][0], ptArray[3][1]);           

            arrowConcaveFactor = getConcaveFactor (ptArray[6][0], ptArray[6][1], ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1], ptArray[5][0], ptArray[5][1], ptArray[3][0], ptArray[3][1]);

            arrowLengthFactor = Math.round((arrowLength/origLineWidth)*100);

            arrowWidthFactor = Math.round((arrowWidth/origLineWidth)*100);           

            lineLengthAng = getAng (arrowEndsMid[0], arrowEndsMid[1],ptArray[4][0], ptArray[4][1]);

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

            ui ()

            //New points

            arrowEndsMid = newPt (ptArray[4][0], ptArray[4][1], newWidth*arrowLengthFactor*.01, lineLengthAng);           

            ptNewArray[5] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan1);

            ptNewArray[3] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan2);

            ptNewArray[1] = newPt (lineMid1[0], lineMid1[1], newWidth/2, lineAngTan2);

            ptNewArray[0] = newPt (lineMid1[0], lineMid1[1], newWidth/2, lineAngTan1);          

            ptTemp1 = newPt (lineMid2[0], lineMid2[1], newWidth/2, lineAngTan1);           

            ptTemp2 = newPt (lineMid2[0], lineMid2[1], newWidth/2, lineAngTan2);             

            headIntersect1= getIntersect (ptTemp1[0], ptTemp1[1], ptNewArray[0][0], ptNewArray[0][1], ptArray[4][0], ptArray[4][1], ptNewArray[5][0], ptNewArray[5][1]);           

            headIntersect2= getIntersect (ptTemp2[0], ptTemp2[1], ptNewArray[1][0], ptNewArray[1][1], ptArray[4][0], ptArray[4][1], ptNewArray[3][0], ptNewArray[3][1]);           

            ptTemp3 = getIntersect (ptTemp1[0], ptTemp1[1], ptNewArray[0][0], ptNewArray[0][1], ptNewArray[5][0], ptNewArray[5][1], ptNewArray[3][0], ptNewArray[3][1]);           

            ptTemp4 = getIntersect (ptTemp2[0], ptTemp2[1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[5][0], ptNewArray[5][1], ptNewArray[3][0], ptNewArray[3][1]);           

            arrowConcave = lineL (headIntersect1[0], headIntersect1[1], ptTemp3[0], ptTemp3[1])*arrowConcaveFactor*.01;           

            ptNewArray[6] = newPt (ptTemp3[0], ptTemp3[1], -arrowConcave, lineLengthAng);           

            ptNewArray[2] = newPt (ptTemp4[0], ptTemp4[1], -arrowConcave, lineLengthAng);          

            }

        else{

            //alert('beginning') 

            lineType = 'Single Arrow Start';

            origLineWidth = lineL (ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1]);

            lineAngTan1 = getAng (ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1]);

            lineAngTan2 = getAng (ptArray[4][0], ptArray[4][1], ptArray[0][0], ptArray[0][1]);

            lineMid1 = [(ptArray[4][0] + ptArray[0][0])/2,(ptArray[4][1] + ptArray[0][1])/2 ]; 

            lineMid2 = [(ptArray[5][0] + ptArray[6][0])/2,(ptArray[5][1] + ptArray[6][1])/2 ];

            arrowEndsMid = [(ptArray[1][0] + ptArray[3][0])/2,(ptArray[1][1] + ptArray[3][1])/2 ]

            arrowLength = lineL (ptArray[2][0], ptArray[2][1], arrowEndsMid[0], arrowEndsMid[1]);        

            arrowWidth = lineL (ptArray[1][0], ptArray[1][1], ptArray[3][0], ptArray[3][1]);

            arrowConcaveFactor = getConcaveFactor (ptArray[0][0], ptArray[0][1], ptArray[6][0], ptArray[6][1], ptArray[2][0], ptArray[2][1], ptArray[1][0], ptArray[1][1], ptArray[3][0], ptArray[3][1])

            arrowLengthFactor = Math.round((arrowLength/origLineWidth)*100);

            arrowWidthFactor = Math.round((arrowWidth/origLineWidth)*100);

            lineLengthAng = getAng (arrowEndsMid[0], arrowEndsMid[1],ptArray[2][0], ptArray[2][1]);

             

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

            ui ()

            //New points

            arrowEndsMid = newPt (ptArray[2][0], ptArray[2][1], newWidth*arrowLengthFactor*.01, lineLengthAng);

            ptNewArray[1] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan1);

            ptNewArray[3] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan2);

            ptNewArray[5] = newPt (lineMid2[0], lineMid2[1], newWidth/2, lineAngTan2);

            ptNewArray[6] = newPt (lineMid2[0], lineMid2[1], newWidth/2, lineAngTan1);

            ptTemp1 = newPt (lineMid1[0], lineMid1[1], newWidth/2, lineAngTan1);

            ptTemp2 = newPt (lineMid1[0], lineMid1[1], newWidth/2, lineAngTan2);   

            headIntersect1= getIntersect (ptTemp1[0], ptTemp1[1], ptNewArray[6][0], ptNewArray[6][1], ptArray[2][0], ptArray[2][1], ptNewArray[1][0], ptNewArray[1][1])

            headIntersect2= getIntersect (ptTemp2[0], ptTemp2[1], ptNewArray[5][0], ptNewArray[5][1], ptArray[2][0], ptArray[2][1], ptNewArray[3][0], ptNewArray[3][1])

            ptTemp3 = getIntersect (ptTemp1[0], ptTemp1[1], ptNewArray[6][0], ptNewArray[6][1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[3][0], ptNewArray[3][1])

            ptTemp4 = getIntersect (ptTemp2[0], ptTemp2[1], ptNewArray[5][0], ptNewArray[5][1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[3][0], ptNewArray[3][1])

            arrowConcave = lineL (headIntersect1[0], headIntersect1[1], ptTemp3[0], ptTemp3[1])*arrowConcaveFactor*.01;

            ptNewArray[0] = newPt (ptTemp3[0], ptTemp3[1], -arrowConcave, lineLengthAng);

            ptNewArray[4] = newPt (ptTemp4[0], ptTemp4[1], -arrowConcave, lineLengthAng);

            }

   

        break;

    case 10:

            lineType = 'Double Arrow';

            origLineWidth = lineL (ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1]);

            lineAngTan1 = getAng (ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1]);

            lineAngTan2 = getAng (ptArray[4][0], ptArray[4][1], ptArray[0][0], ptArray[0][1]);                

            arrowEndsMid = [(ptArray[1][0] + ptArray[3][0])/2,(ptArray[1][1] + ptArray[3][1])/2 ];           

            arrowLength = lineL (ptArray[2][0], ptArray[2][1], arrowEndsMid[0], arrowEndsMid[1]);            

            arrowWidth = lineL (ptArray[1][0], ptArray[1][1], ptArray[3][0], ptArray[3][1]);           

            arrowConcaveFactor = getConcaveFactor (ptArray[0][0], ptArray[0][1], ptArray[9][0], ptArray[9][1], ptArray[2][0], ptArray[2][1], ptArray[1][0], ptArray[1][1], ptArray[3][0], ptArray[3][1]);

            arrowLengthFactor = Math.round((arrowLength/origLineWidth)*100);

            arrowWidthFactor = Math.round((arrowWidth/origLineWidth)*100);

            lineLengthAng = getAng (ptArray[7][0], ptArray[7][1],ptArray[2][0], ptArray[2][1]);   

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

            ui ()

            //new points

            arrowEndsMid = newPt (ptArray[2][0], ptArray[2][1], newWidth*arrowLengthFactor*.01, lineLengthAng);

            ptNewArray[1] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan1);           

            ptNewArray[3] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan2);

            arrowEndsMid = newPt (ptArray[7][0], ptArray[7][1], -newWidth*arrowLengthFactor*.01, lineLengthAng);

            ptNewArray[8] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan1);           

            ptNewArray[6] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan2);           

            ptTemp1 = newPt (ptArray[2][0], ptArray[2][1], newWidth/2, lineAngTan1);

            var ptTemp1a = newPt (ptArray[7][0], ptArray[7][1], newWidth/2, lineAngTan1);

            ptTemp2 = newPt (ptArray[2][0], ptArray[2][1], newWidth/2, lineAngTan2);

            var ptTemp2a = newPt (ptArray[7][0], ptArray[7][1], newWidth/2, lineAngTan2);

           

            headIntersect1= getIntersect (ptTemp1[0], ptTemp1[1], ptTemp1a[0], ptTemp1a[1], ptArray[2][0], ptArray[2][1], ptNewArray[1][0], ptNewArray[1][1]);

            headIntersect2= getIntersect (ptTemp2[0], ptTemp2[1], ptTemp2a[0], ptTemp2a[1], ptArray[2][0], ptArray[2][1], ptNewArray[3][0], ptNewArray[3][1]);

            var headIntersect3= getIntersect (ptTemp1[0], ptTemp1[1], ptTemp1a[0], ptTemp1a[1], ptArray[7][0], ptArray[7][1], ptNewArray[8][0], ptNewArray[8][1]);

            var headIntersect4= getIntersect (ptTemp2[0], ptTemp2[1], ptTemp2a[0], ptTemp2a[1], ptArray[7][0], ptArray[7][1], ptNewArray[6][0], ptNewArray[6][1]);

            ptTemp3 = getIntersect (ptTemp1[0], ptTemp1[1], ptTemp1a[0], ptTemp1a[1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[3][0], ptNewArray[3][1]);

            var ptTemp3a = getIntersect (ptTemp2[0], ptTemp2[1], ptTemp2a[0], ptTemp2a[1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[3][0], ptNewArray[3][1]);

            ptTemp4 = getIntersect (ptTemp1[0], ptTemp1[1], ptTemp1a[0], ptTemp1a[1], ptNewArray[6][0], ptNewArray[6][1], ptNewArray[8][0], ptNewArray[8][1]);

            var ptTemp4a = getIntersect (ptTemp2[0], ptTemp2[1], ptTemp2a[0], ptTemp2a[1], ptNewArray[6][0], ptNewArray[6][1], ptNewArray[8][0], ptNewArray[8][1]);

           

           arrowConcave = lineL (headIntersect1[0], headIntersect1[1], ptTemp3[0], ptTemp3[1])*arrowConcaveFactor*.01;

           ptNewArray[0] = newPt (ptTemp3[0], ptTemp3[1], -arrowConcave, lineLengthAng);

           ptNewArray[4] = newPt (ptTemp3a[0], ptTemp3a[1], -arrowConcave, lineLengthAng);     

          

           ptNewArray[9] = newPt (ptTemp4[0], ptTemp4[1], arrowConcave, lineLengthAng);

           ptNewArray[5] = newPt (ptTemp4a[0], ptTemp4a[1], arrowConcave, lineLengthAng);             

           

        break;

        default:

        run = false;

        alert("The layer selected didn't match the criteria for a line or arrow")

    }//end switch

if(run){

    var myPathInfo = mkNewPathInfo ();

    deltPath ();

    var tempPath = app.activeDocument.pathItems.add( 'temp', myPathInfo);

    selPath ();

    doc.activeLayer = sLay;

    mkPath ()

    tempPath.remove();

    }

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

function ui(){

    var dlg = new Window('dialog','Edit Line Tool Line');

        dlg.location =[1800,200];

        dlg.alignChildren = ['left','top'];

            dlg.lType = dlg.add('statictext',undefined,lineType);       

            dlg.wGp = dlg.add('group');

                dlg.wGp.alignChildren = ['left','top'];

                dlg.wGp.sTxts = dlg.wGp.add('statictext',undefined,'Line Width');

                dlg.wGp.eTxt = dlg.wGp.add('edittext',undefined,Math.round(origLineWidth));

                    dlg.wGp.eTxt.size = [50,12];

                dlg.wGp.sTxte = dlg.wGp.add('statictext',undefined,'px');

               

            if(lineType!='Normal Line'){

                for(var i=0;i<xmlPref.prefs.arrows.children().length();i++){

                    dropLst= xmlPref.prefs.arrows.children().@preset

                    }

                }

            else{

                for(var i=0;i<xmlPref.prefs.lines.children().length();i++){

                    dropLst= xmlPref.prefs.lines.children().@preset

                    }              

                }

            if(lineType!='Normal Line'){

                dlg.aLgp = dlg.add('group');

                    dlg.aLgp.alignChildren = ['left','top'];

                    dlg.aLgp.sTxts = dlg.aLgp.add('statictext',undefined,'Arrow Length');

                    dlg.aLgp.ALen = dlg.aLgp.add('edittext',undefined,arrowLengthFactor);

                        dlg.aLgp.ALen.size = [50,12];

                    dlg.aLgp.sTxte = dlg.aLgp.add('statictext',undefined,'%');

                   

                dlg.aWgp = dlg.add('group');

                    dlg.aWgp.alignChildren = ['left','top'];

                    dlg.aWgp.sTxts = dlg.aWgp.add('statictext',undefined,'Arrow Width');

                    dlg.aWgp.AWid = dlg.aWgp.add('edittext',undefined,arrowWidthFactor);

                        dlg.aWgp.AWid.size = [50,12];

                    dlg.aWgp.sTxte = dlg.aWgp.add('statictext',undefined,'%');    

                   

                dlg.aConGp = dlg.add('group');

                    dlg.aConGp.alignChildren = ['left','top'];

                    dlg.aConGp.sTxts = dlg.aConGp.add('statictext',undefined,'Arrow Concave');

                    dlg.aConGp.ACon = dlg.aConGp.add('edittext',undefined,arrowConcaveFactor);

                        dlg.aConGp.ACon.size = [50,12];

                    dlg.aConGp.sTxte = dlg.aConGp.add('statictext',undefined,'%');                     

                }

           

            dlg.btnGp = dlg.add('group');

            dlg.btnGp.okay = dlg.btnGp.add('button',undefined,'Okay');

            dlg.btnGp.cancel = dlg.btnGp.add('button',undefined,'Cancel');

           

        dlg.prefsPn = dlg.add('panel',undefined,'Preferences');

            dlg.prefsPn.alignChildren = ['left','top'];

            dlg.prefsPn.save = dlg.prefsPn.add('button',undefined,'Save Preference');

            dlg.prefsPn.del = dlg.prefsPn.add('button',undefined,'Delete Preference');

           

            prefsDrop = dlg.prefsPn.add('dropdownlist',undefined,dropLst);

            prefsDrop.title = 'Load Preferences';           

            prefsDrop.size = [300,25];     

           

        prefsDrop.onChange = function(){

            if(lineType!='Normal Line'){

                dlg.wGp.eTxt.text = xmlPref.prefs.arrows.children()[parseInt(prefsDrop.selection)].width

                dlg.aLgp.ALen.text = xmlPref.prefs.arrows.children()[parseInt(prefsDrop.selection)].leng

                dlg.aWgp.AWid.text = xmlPref.prefs.arrows.children()[parseInt(prefsDrop.selection)].aWidth

                dlg.aConGp.ACon.text = xmlPref.prefs.arrows.children()[parseInt(prefsDrop.selection)].concave

                }

            else{

                dlg.wGp.eTxt.text = xmlPref.prefs.lines.children()[parseInt(prefsDrop.selection)].width

                }

            };

           

        dlg.wGp.eTxt.onChange = function(){

            textToNum (1, 1000, dlg.wGp.eTxt, origLineWidth);

            }

        if(lineType!='Normal Line'){       

            dlg.aLgp.ALen.onChange = function(){

                textToNum (1, 10000, dlg.aLgp.ALen, arrowLengthFactor);

                }      

           

            dlg.aWgp.AWid.onChange = function(){

                textToNum (1, 10000, dlg.aWgp.AWid, arrowWidthFactor);

                }

           

            dlg.aWgp.AWid.onChange = function(){

                textToNum (-50, 50, dlg.aConGp.ACon, arrowConcaveFactor);

                }   

        }//end if

           

            dlg.prefsPn.save.onClick = function(){

                savePrefs ();

                }

           

            dlg.prefsPn.del.onClick = function(){

                if(prefsDrop.selection != null){

                    var selc = parseInt(prefsDrop.selection);                   

                    prefsDrop.remove(selc);

                    if(lineType!='Normal Line'){

                        delete xmlPref.prefs.arrows.children()[selc];

                        }

                    else{

                        delete xmlPref.prefs.lines.children()[selc];

                        }

                    writeXMLFile (xmlFile, xmlPref)

                    }

                }           

           

        dlg.btnGp.okay.onClick = function(){

            dlg.close();

            newWidth = parseInt (dlg.wGp.eTxt.text);

                if(lineType!='Normal Line'){

                arrowLengthFactor = parseInt (dlg.aLgp.ALen.text);

                arrowWidthFactor = parseInt (dlg.aWgp.AWid.text);

                arrowConcaveFactor = parseInt (dlg.aConGp.ACon.text);

                }

            }

       

        dlg.btnGp.cancel.onClick = function(){           

            run = false;

            dlg.close()

            } 

//==================

function savePrefs(){

    var newName = prompt ('Enter New Profile Name', '', 'Save Preferences');

    var prefGood = true;

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

        if(prefsDrop.items.text == newName){

            newName = prompt ('That preset exists\nPlease choose a unique name','', 'Save Preferences' );

            i=0

            }

        }

        prefsDrop.add('item',newName)

        if(lineType=='Normal Line'){

            xmlPref.prefs.lines.appendChild (XML('<line preset="'+ newName+ '"><width>'+dlg.wGp.eTxt.text+'</width></line>'));

            }

        else{  

            xmlPref.prefs.arrows.appendChild (XML('<arrow preset="'+ newName+ '"><width>'+dlg.wGp.eTxt.text+'</width><leng>'+dlg.aLgp.ALen.text+'</leng><aWidth>'+dlg.aWgp.AWid.text+'</aWidth><concave>'+dlg.aConGp.ACon.text+'</concave></arrow>'));

            }

        writeXMLFile (xmlFile, xmlPref)

    }

//=====================       

    dlg.show();

    }

function textToNum(sMin,sMax,e,def){

    def=Math.round (def)

    var sHold = def;

            if(isNaN(parseInt(e.text))){

            alert('"' + e.text + '" is not a number\nEnter a value between ' + sMin + '-' + sMax );

            e.text = def};

            else{

                sHold = parseInt(e.text)

            if(sHold < sMin){

                rangeAlert();

                sHold = sMin;               

                };

            if(sHold > sMax){

                rangeAlert();

                sHold = sMax;

                };

            e.text = sHold;

            }

    function rangeAlert(){alert('Number range must be between ' + sMin + '-' + sMax)};

};//end function textToNum

function getConcaveFactor(x1,y1,x2,y2, x3, y3, x4, y4, x5, y5){//1 & 2 =  shaft pt 1 &2; 3 & 4 = arrow length line; 5 = tail point opp side

    var ptAH = getIntersect (x1, y1, x2, y2, x3, y3, x4, y4);//intersection of shaft with sides of arrowhead

    //mkDot (ptAH)

    var ptTail = getIntersect (x1, y1, x2, y2, x4, y4, x5, y5);//Intersection of arrow tip ends cross shaft

    var conTotalLen = lineL (x1, y1, ptAH[0], ptAH[1]);//gets total length to see if the concave goes in toward the arrowhead or out

    var conFullLen =  lineL (ptTail[0], ptTail[1], ptAH[0], ptAH[1]);//length of arrow from end tips to intersection with shaft

    var conF = lineL (x1, y1, ptTail[0], ptTail[1])/conFullLen

    if(conTotalLen>conFullLen){conF*=-1}

    return Math.round(conF*100)

    }

function getIntersect(x1,y1,x2,y2, x3, y3, x4, y4){

    var slope1 = (y1-y2)/(x1-x2);

    var bIntersect1 = y1-(slope1*x1)

    var slope2 = (y3-y4)/(x3-x4);

    var bIntersect2 = y3-(slope2*x3) 

    var xNew ;

    var yNew;

    if(bIntersect1=='-Infinity'||bIntersect1=='Infinity'){

        xNew=x1;

        yNew = slope2*xNew + bIntersect2;

        }

    else if(bIntersect2=='-Infinity'||bIntersect2=='Infinity'){

        xNew = x3;

        yNew = slope1*xNew + bIntersect1;

        }

    else{

        xNew= (-(bIntersect1-bIntersect2))/(slope1-slope2);

        yNew = slope1*xNew + bIntersect1

        }

   

   

    return [xNew,yNew]

    }

function recordAnchors(pathObj){

    ptArray = new Array();

    for(var i=0;i<pathObj.subPathItems[0].pathPoints.length;i++){

        ptNewArray = ptArray = pathObj.subPathItems[0].pathPoints.anchor;

        }//end loop

    }//end function

function mkNewPathInfo(){

    var pathArray = new Array();

    var piArray = new Array();

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

         piArray = new PathPointInfo;

         piArray.kind = cPath.subPathItems[0].pathPoints.kind;

         piArray.anchor = ptNewArray;

         piArray.leftDirection = ptNewArray;

         piArray.rightDirection = ptNewArray;

        }//end loop

    pathArray[0] = new SubPathInfo();

    pathArray[0].operation = cPath.subPathItems[0].operation;

    pathArray[0].closed = cPath.subPathItems[0].closed;

    pathArray[0].entireSubPath = piArray; 

    return pathArray;

    };//end function

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

    function extractSubPathInfo(pathObj,oldPoint,newPoint){

        var pathArray = new Array();

        var pl = pathObj.subPathItems.length;

        for(var s=0;s<pl;s++){

            var pArray = new Array();

              for(var i=0;i<pathObj.subPathItems.pathPoints.length;i++){

                 pArray = new PathPointInfo;

                 pArray.kind = pathObj.subPathItems.pathPoints.kind;

             if(pathObj.subPathItems.pathPoints.anchor[0]==oldPoint[0] &&

                   pathObj.subPathItems.pathPoints.anchor[1]==oldPoint[1]){

                pArray.anchor = newPoint;

                pArray.leftDirection = newPoint;

                pArray.rightDirection = newPoint;

             }else{

                pArray.anchor = pathObj.subPathItems.pathPoints.anchor;

                pArray.leftDirection = pathObj.subPathItems.pathPoints.leftDirection;

                pArray.rightDirection = pathObj.subPathItems.pathPoints.rightDirection;

             }

              };

            pathArray[pathArray.length] = new Array();

            pathArray[pathArray.length - 1] = new SubPathInfo();

            pathArray[pathArray.length - 1].operation = pathObj.subPathItems.operation;

            pathArray[pathArray.length - 1].closed = pathObj.subPathItems.closed;

            pathArray[pathArray.length - 1].entireSubPath = pArray;

        };

        return pathArray;

    };

       

    function deltPath(){

        var idDlt = charIDToTypeID( "Dlt " );

        var desc2 = new ActionDescriptor();

        var idnull = charIDToTypeID( "null" );

            var ref1 = new ActionReference();

            idPath = charIDToTypeID( "Path" );

            var idvectorMask = stringIDToTypeID( "vectorMask" );

            ref1.putEnumerated( idPath, idPath, idvectorMask );

            var idLyr = charIDToTypeID( "Lyr " );

            var idOrdn = charIDToTypeID( "Ordn" );

            var idTrgt = charIDToTypeID( "Trgt" );

            ref1.putEnumerated( idLyr, idOrdn, idTrgt );

        desc2.putReference( idnull, ref1 );

        executeAction( idDlt, desc2, DialogModes.NO );

        }

   

    function selPath(){

         var idslct = charIDToTypeID( "slct" );

            var desc2 = new ActionDescriptor();

            var idnull = charIDToTypeID( "null" );

                var ref1 = new ActionReference();

                var idPath = charIDToTypeID( "Path" );

                ref1.putName( idPath, "temp" );

            desc2.putReference( idnull, ref1 );

        executeAction( idslct, desc2, DialogModes.NO );      

        }

   

    function mkPath(){

         var idMk = charIDToTypeID( "Mk  " );

            var desc10 = new ActionDescriptor();

            var idnull = charIDToTypeID( "null" );

                var ref3 = new ActionReference();

                var idPath = charIDToTypeID( "Path" );

                ref3.putClass( idPath );

            desc10.putReference( idnull, ref3 );

            var idAt = charIDToTypeID( "At  " );

                var ref4 = new ActionReference();

                var idPath = charIDToTypeID( "Path" );

                var idPath = charIDToTypeID( "Path" );

                var idvectorMask = stringIDToTypeID( "vectorMask" );

                ref4.putEnumerated( idPath, idPath, idvectorMask );

            desc10.putReference( idAt, ref4 );

            var idUsng = charIDToTypeID( "Usng" );

                var ref5 = new ActionReference();

                var idPath = charIDToTypeID( "Path" );

                var idOrdn = charIDToTypeID( "Ordn" );

                var idTrgt = charIDToTypeID( "Trgt" );

                ref5.putEnumerated( idPath, idOrdn, idTrgt );

            desc10.putReference( idUsng, ref5 );

        executeAction( idMk, desc10, DialogModes.NO );      

        }

   

function lineL (ax,ay,bx,by){

    var x = Math.abs (ax-bx);

    var y = Math.abs (ay-by);

    var len = Math.sqrt (Math.pow (x, 2) + Math.pow (y, 2));

    return len

    }

function getAng(ax,ay,bx,by){

    var dx = ax-bx;

    var dy = ay-by;

    var theta = Math.atan2 (dy, dx);

    //theta *= 180/Math.PI

    return theta;

    }

function newPt (x1,y1,rad,ang){

    var newEnd = new Array();

    newEnd[0] = x1 + rad * Math.cos (ang);

    newEnd[1] = y1 + rad * Math.sin (ang);

    return newEnd;

    }

//===============READ/WRITE functions========================================

//=========================================================================

function readXMLFile(file) {

    if (!file.exists) {

        alert( "Cannot find file: " + deodeURI(file.absoluteURI));

        }

    else{

        file.encoding = "UTF8";

        file.lineFeed = "unix";

        file.open("r", "TEXT", "????");

        var str = file.read();

        file.close();

        return new XML(str);

        };

};

function writeXMLFile(file, xml) {

    if (!(xml instanceof XML)) {

        alert( "Bad XML parameter");

        };

    else{

        file.encoding = "UTF8";

        file.open("w", "TEXT", "????");

        //unicode signature, this is UTF16 but will convert to UTF8 "EF BB BF"

        file.write("\uFEFF");

        file.lineFeed = "unix";

        file.write(xml.toXMLString());

        file.close();

        };

    };

//=========================================================================

6 replies

Chuck Uebele
Community Expert
Chuck UebeleCommunity ExpertCorrect answer
Community Expert
July 9, 2019

Here is a script that will change the line width and size of arrowheads. It will not change a line into an arrow or an arrow into a line.

#target photoshop

//copyright 2017 Chuck Uebele, all rights reserved

//Use at your own risk.

var xmlFile = new File(Folder.desktop+'/ArrowPrefs.xml');

var xmlPref

if(xmlFile.exists){

    xmlPref = readXMLFile (xmlFile)

    //alert(xmlPref.prefs.lines.children().length())

    //alert(xmlPref.prefs.lines.children()[0].@preset)

    }

else{xmlPref = new XML('<root><prefs><lines/><arrows/></prefs>')};

//varables for lines and points

var run = true;

var lineType;

var origLineWidth;

var lineAngTan1;//from first point to oppsite side of line

var lineAngTan2;//From oppsite side of line to first point

var lineLengthAng;

var lineLength;

var lineMid1;//mid width on line from first point

var lineMid2;//mid width on line from oppsite end of line

var newWidth = 20

var ptTemp1

var ptTemp2

var ptTemp3

var ptTemp4

var dropLst = new Array()

var prefsDrop

var headIntersect1;

var headIntersect2;

//-----------

var arrowLength;

var arrowWidth;

var arrowEndsMid;

var arrowConcave;

var arrowConcaveFactor;

var arrowLengthFactor;

var arrowWidthFactor;

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

app.preferences.rulerUnits = Units.PIXELS;

try{

    var doc = activeDocument

    var sLay = doc.activeLayer

    var sLayName = sLay.name + ' Shape Path'

    var cPath = doc.pathItems.getByName(sLayName)

    var ptArray = new Array();

    var ptNewArray = new Array();

    var idPath;

//var numAnchors = cPath.subPathItems[0].pathPoints.length;

recordAnchors (cPath);

var numAnchors = ptArray.length;

    }

catch(e){

    run = false;

    var numAnchors=0

    }

switch(numAnchors){

    case 4:

        lineType = 'Normal Line'

        origLineWidth = lineL (ptArray[0][0], ptArray[0][1], ptArray[1][0], ptArray[1][1]);

        lineAngTan1 = getAng (ptArray[0][0], ptArray[0][1], ptArray[1][0], ptArray[1][1]);

        lineAngTan2 = getAng (ptArray[1][0], ptArray[1][1], ptArray[0][0], ptArray[0][1]);

        lineMid1 = [(ptArray[0][0] + ptArray[1][0])/2,(ptArray[0][1] + ptArray[1][1])/2 ]; 

        lineMid2 = [(ptArray[2][0] + ptArray[3][0])/2,(ptArray[2][1] + ptArray[3][1])/2 ];

       

        ui ();

       

        ptNewArray[0] = newPt (lineMid1[0],lineMid1[1], newWidth/2, lineAngTan1);

        ptNewArray[3] = newPt (lineMid2[0],lineMid2[1], newWidth/2, lineAngTan1);

        ptNewArray[1] = newPt (lineMid1[0],lineMid1[1], newWidth/2, lineAngTan2);

        ptNewArray[2] = newPt (lineMid2[0],lineMid2[1], newWidth/2, lineAngTan2);

        break;

    case 7:

        if(Math.round (getAng (ptArray[0][0], ptArray[0][1], ptArray[6][0], ptArray[6][1]))==Math.round (getAng (ptArray[1][0], ptArray[1][1], ptArray[2][0], ptArray[2][1]))){

            //alert('end')

            lineType = 'Single Arrow End';

            origLineWidth = lineL (ptArray[0][0], ptArray[0][1], ptArray[1][0], ptArray[1][1]);

            lineAngTan1 = getAng (ptArray[0][0], ptArray[0][1], ptArray[1][0], ptArray[1][1]);

            lineAngTan2 = getAng (ptArray[1][0], ptArray[1][1], ptArray[0][0], ptArray[0][1]);

            lineMid1 = [(ptArray[1][0] + ptArray[0][0])/2,(ptArray[1][1] + ptArray[0][1])/2 ]; 

            lineMid2 = [(ptArray[2][0] + ptArray[6][0])/2,(ptArray[2][1] + ptArray[6][1])/2 ];

            arrowEndsMid = [(ptArray[3][0] + ptArray[5][0])/2,(ptArray[3][1] + ptArray[5][1])/2 ];           

            arrowLength = lineL (ptArray[4][0], ptArray[4][1], arrowEndsMid[0], arrowEndsMid[1]);             

            arrowWidth = lineL (ptArray[5][0], ptArray[5][1], ptArray[3][0], ptArray[3][1]);           

            arrowConcaveFactor = getConcaveFactor (ptArray[6][0], ptArray[6][1], ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1], ptArray[5][0], ptArray[5][1], ptArray[3][0], ptArray[3][1]);

            arrowLengthFactor = Math.round((arrowLength/origLineWidth)*100);

            arrowWidthFactor = Math.round((arrowWidth/origLineWidth)*100);           

            lineLengthAng = getAng (arrowEndsMid[0], arrowEndsMid[1],ptArray[4][0], ptArray[4][1]);

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

            ui ()

            //New points

            arrowEndsMid = newPt (ptArray[4][0], ptArray[4][1], newWidth*arrowLengthFactor*.01, lineLengthAng);           

            ptNewArray[5] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan1);

            ptNewArray[3] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan2);

            ptNewArray[1] = newPt (lineMid1[0], lineMid1[1], newWidth/2, lineAngTan2);

            ptNewArray[0] = newPt (lineMid1[0], lineMid1[1], newWidth/2, lineAngTan1);          

            ptTemp1 = newPt (lineMid2[0], lineMid2[1], newWidth/2, lineAngTan1);           

            ptTemp2 = newPt (lineMid2[0], lineMid2[1], newWidth/2, lineAngTan2);             

            headIntersect1= getIntersect (ptTemp1[0], ptTemp1[1], ptNewArray[0][0], ptNewArray[0][1], ptArray[4][0], ptArray[4][1], ptNewArray[5][0], ptNewArray[5][1]);           

            headIntersect2= getIntersect (ptTemp2[0], ptTemp2[1], ptNewArray[1][0], ptNewArray[1][1], ptArray[4][0], ptArray[4][1], ptNewArray[3][0], ptNewArray[3][1]);           

            ptTemp3 = getIntersect (ptTemp1[0], ptTemp1[1], ptNewArray[0][0], ptNewArray[0][1], ptNewArray[5][0], ptNewArray[5][1], ptNewArray[3][0], ptNewArray[3][1]);           

            ptTemp4 = getIntersect (ptTemp2[0], ptTemp2[1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[5][0], ptNewArray[5][1], ptNewArray[3][0], ptNewArray[3][1]);           

            arrowConcave = lineL (headIntersect1[0], headIntersect1[1], ptTemp3[0], ptTemp3[1])*arrowConcaveFactor*.01;           

            ptNewArray[6] = newPt (ptTemp3[0], ptTemp3[1], -arrowConcave, lineLengthAng);           

            ptNewArray[2] = newPt (ptTemp4[0], ptTemp4[1], -arrowConcave, lineLengthAng);          

            }

        else{

            //alert('beginning') 

            lineType = 'Single Arrow Start';

            origLineWidth = lineL (ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1]);

            lineAngTan1 = getAng (ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1]);

            lineAngTan2 = getAng (ptArray[4][0], ptArray[4][1], ptArray[0][0], ptArray[0][1]);

            lineMid1 = [(ptArray[4][0] + ptArray[0][0])/2,(ptArray[4][1] + ptArray[0][1])/2 ]; 

            lineMid2 = [(ptArray[5][0] + ptArray[6][0])/2,(ptArray[5][1] + ptArray[6][1])/2 ];

            arrowEndsMid = [(ptArray[1][0] + ptArray[3][0])/2,(ptArray[1][1] + ptArray[3][1])/2 ]

            arrowLength = lineL (ptArray[2][0], ptArray[2][1], arrowEndsMid[0], arrowEndsMid[1]);        

            arrowWidth = lineL (ptArray[1][0], ptArray[1][1], ptArray[3][0], ptArray[3][1]);

            arrowConcaveFactor = getConcaveFactor (ptArray[0][0], ptArray[0][1], ptArray[6][0], ptArray[6][1], ptArray[2][0], ptArray[2][1], ptArray[1][0], ptArray[1][1], ptArray[3][0], ptArray[3][1])

            arrowLengthFactor = Math.round((arrowLength/origLineWidth)*100);

            arrowWidthFactor = Math.round((arrowWidth/origLineWidth)*100);

            lineLengthAng = getAng (arrowEndsMid[0], arrowEndsMid[1],ptArray[2][0], ptArray[2][1]);

             

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

            ui ()

            //New points

            arrowEndsMid = newPt (ptArray[2][0], ptArray[2][1], newWidth*arrowLengthFactor*.01, lineLengthAng);

            ptNewArray[1] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan1);

            ptNewArray[3] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan2);

            ptNewArray[5] = newPt (lineMid2[0], lineMid2[1], newWidth/2, lineAngTan2);

            ptNewArray[6] = newPt (lineMid2[0], lineMid2[1], newWidth/2, lineAngTan1);

            ptTemp1 = newPt (lineMid1[0], lineMid1[1], newWidth/2, lineAngTan1);

            ptTemp2 = newPt (lineMid1[0], lineMid1[1], newWidth/2, lineAngTan2);   

            headIntersect1= getIntersect (ptTemp1[0], ptTemp1[1], ptNewArray[6][0], ptNewArray[6][1], ptArray[2][0], ptArray[2][1], ptNewArray[1][0], ptNewArray[1][1])

            headIntersect2= getIntersect (ptTemp2[0], ptTemp2[1], ptNewArray[5][0], ptNewArray[5][1], ptArray[2][0], ptArray[2][1], ptNewArray[3][0], ptNewArray[3][1])

            ptTemp3 = getIntersect (ptTemp1[0], ptTemp1[1], ptNewArray[6][0], ptNewArray[6][1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[3][0], ptNewArray[3][1])

            ptTemp4 = getIntersect (ptTemp2[0], ptTemp2[1], ptNewArray[5][0], ptNewArray[5][1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[3][0], ptNewArray[3][1])

            arrowConcave = lineL (headIntersect1[0], headIntersect1[1], ptTemp3[0], ptTemp3[1])*arrowConcaveFactor*.01;

            ptNewArray[0] = newPt (ptTemp3[0], ptTemp3[1], -arrowConcave, lineLengthAng);

            ptNewArray[4] = newPt (ptTemp4[0], ptTemp4[1], -arrowConcave, lineLengthAng);

            }

   

        break;

    case 10:

            lineType = 'Double Arrow';

            origLineWidth = lineL (ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1]);

            lineAngTan1 = getAng (ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1]);

            lineAngTan2 = getAng (ptArray[4][0], ptArray[4][1], ptArray[0][0], ptArray[0][1]);                

            arrowEndsMid = [(ptArray[1][0] + ptArray[3][0])/2,(ptArray[1][1] + ptArray[3][1])/2 ];           

            arrowLength = lineL (ptArray[2][0], ptArray[2][1], arrowEndsMid[0], arrowEndsMid[1]);            

            arrowWidth = lineL (ptArray[1][0], ptArray[1][1], ptArray[3][0], ptArray[3][1]);           

            arrowConcaveFactor = getConcaveFactor (ptArray[0][0], ptArray[0][1], ptArray[9][0], ptArray[9][1], ptArray[2][0], ptArray[2][1], ptArray[1][0], ptArray[1][1], ptArray[3][0], ptArray[3][1]);

            arrowLengthFactor = Math.round((arrowLength/origLineWidth)*100);

            arrowWidthFactor = Math.round((arrowWidth/origLineWidth)*100);

            lineLengthAng = getAng (ptArray[7][0], ptArray[7][1],ptArray[2][0], ptArray[2][1]);   

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

            ui ()

            //new points

            arrowEndsMid = newPt (ptArray[2][0], ptArray[2][1], newWidth*arrowLengthFactor*.01, lineLengthAng);

            ptNewArray[1] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan1);           

            ptNewArray[3] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan2);

            arrowEndsMid = newPt (ptArray[7][0], ptArray[7][1], -newWidth*arrowLengthFactor*.01, lineLengthAng);

            ptNewArray[8] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan1);           

            ptNewArray[6] = newPt (arrowEndsMid[0], arrowEndsMid[1], (newWidth*arrowWidthFactor *.01)/2, lineAngTan2);           

            ptTemp1 = newPt (ptArray[2][0], ptArray[2][1], newWidth/2, lineAngTan1);

            var ptTemp1a = newPt (ptArray[7][0], ptArray[7][1], newWidth/2, lineAngTan1);

            ptTemp2 = newPt (ptArray[2][0], ptArray[2][1], newWidth/2, lineAngTan2);

            var ptTemp2a = newPt (ptArray[7][0], ptArray[7][1], newWidth/2, lineAngTan2);

           

            headIntersect1= getIntersect (ptTemp1[0], ptTemp1[1], ptTemp1a[0], ptTemp1a[1], ptArray[2][0], ptArray[2][1], ptNewArray[1][0], ptNewArray[1][1]);

            headIntersect2= getIntersect (ptTemp2[0], ptTemp2[1], ptTemp2a[0], ptTemp2a[1], ptArray[2][0], ptArray[2][1], ptNewArray[3][0], ptNewArray[3][1]);

            var headIntersect3= getIntersect (ptTemp1[0], ptTemp1[1], ptTemp1a[0], ptTemp1a[1], ptArray[7][0], ptArray[7][1], ptNewArray[8][0], ptNewArray[8][1]);

            var headIntersect4= getIntersect (ptTemp2[0], ptTemp2[1], ptTemp2a[0], ptTemp2a[1], ptArray[7][0], ptArray[7][1], ptNewArray[6][0], ptNewArray[6][1]);

            ptTemp3 = getIntersect (ptTemp1[0], ptTemp1[1], ptTemp1a[0], ptTemp1a[1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[3][0], ptNewArray[3][1]);

            var ptTemp3a = getIntersect (ptTemp2[0], ptTemp2[1], ptTemp2a[0], ptTemp2a[1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[3][0], ptNewArray[3][1]);

            ptTemp4 = getIntersect (ptTemp1[0], ptTemp1[1], ptTemp1a[0], ptTemp1a[1], ptNewArray[6][0], ptNewArray[6][1], ptNewArray[8][0], ptNewArray[8][1]);

            var ptTemp4a = getIntersect (ptTemp2[0], ptTemp2[1], ptTemp2a[0], ptTemp2a[1], ptNewArray[6][0], ptNewArray[6][1], ptNewArray[8][0], ptNewArray[8][1]);

           

           arrowConcave = lineL (headIntersect1[0], headIntersect1[1], ptTemp3[0], ptTemp3[1])*arrowConcaveFactor*.01;

           ptNewArray[0] = newPt (ptTemp3[0], ptTemp3[1], -arrowConcave, lineLengthAng);

           ptNewArray[4] = newPt (ptTemp3a[0], ptTemp3a[1], -arrowConcave, lineLengthAng);     

          

           ptNewArray[9] = newPt (ptTemp4[0], ptTemp4[1], arrowConcave, lineLengthAng);

           ptNewArray[5] = newPt (ptTemp4a[0], ptTemp4a[1], arrowConcave, lineLengthAng);             

           

        break;

        default:

        run = false;

        alert("The layer selected didn't match the criteria for a line or arrow")

    }//end switch

if(run){

    var myPathInfo = mkNewPathInfo ();

    deltPath ();

    var tempPath = app.activeDocument.pathItems.add( 'temp', myPathInfo);

    selPath ();

    doc.activeLayer = sLay;

    mkPath ()

    tempPath.remove();

    }

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

function ui(){

    var dlg = new Window('dialog','Edit Line Tool Line');

        dlg.location =[1800,200];

        dlg.alignChildren = ['left','top'];

            dlg.lType = dlg.add('statictext',undefined,lineType);       

            dlg.wGp = dlg.add('group');

                dlg.wGp.alignChildren = ['left','top'];

                dlg.wGp.sTxts = dlg.wGp.add('statictext',undefined,'Line Width');

                dlg.wGp.eTxt = dlg.wGp.add('edittext',undefined,Math.round(origLineWidth));

                    dlg.wGp.eTxt.size = [50,12];

                dlg.wGp.sTxte = dlg.wGp.add('statictext',undefined,'px');

               

            if(lineType!='Normal Line'){

                for(var i=0;i<xmlPref.prefs.arrows.children().length();i++){

                    dropLst= xmlPref.prefs.arrows.children().@preset

                    }

                }

            else{

                for(var i=0;i<xmlPref.prefs.lines.children().length();i++){

                    dropLst= xmlPref.prefs.lines.children().@preset

                    }              

                }

            if(lineType!='Normal Line'){

                dlg.aLgp = dlg.add('group');

                    dlg.aLgp.alignChildren = ['left','top'];

                    dlg.aLgp.sTxts = dlg.aLgp.add('statictext',undefined,'Arrow Length');

                    dlg.aLgp.ALen = dlg.aLgp.add('edittext',undefined,arrowLengthFactor);

                        dlg.aLgp.ALen.size = [50,12];

                    dlg.aLgp.sTxte = dlg.aLgp.add('statictext',undefined,'%');

                   

                dlg.aWgp = dlg.add('group');

                    dlg.aWgp.alignChildren = ['left','top'];

                    dlg.aWgp.sTxts = dlg.aWgp.add('statictext',undefined,'Arrow Width');

                    dlg.aWgp.AWid = dlg.aWgp.add('edittext',undefined,arrowWidthFactor);

                        dlg.aWgp.AWid.size = [50,12];

                    dlg.aWgp.sTxte = dlg.aWgp.add('statictext',undefined,'%');    

                   

                dlg.aConGp = dlg.add('group');

                    dlg.aConGp.alignChildren = ['left','top'];

                    dlg.aConGp.sTxts = dlg.aConGp.add('statictext',undefined,'Arrow Concave');

                    dlg.aConGp.ACon = dlg.aConGp.add('edittext',undefined,arrowConcaveFactor);

                        dlg.aConGp.ACon.size = [50,12];

                    dlg.aConGp.sTxte = dlg.aConGp.add('statictext',undefined,'%');                     

                }

           

            dlg.btnGp = dlg.add('group');

            dlg.btnGp.okay = dlg.btnGp.add('button',undefined,'Okay');

            dlg.btnGp.cancel = dlg.btnGp.add('button',undefined,'Cancel');

           

        dlg.prefsPn = dlg.add('panel',undefined,'Preferences');

            dlg.prefsPn.alignChildren = ['left','top'];

            dlg.prefsPn.save = dlg.prefsPn.add('button',undefined,'Save Preference');

            dlg.prefsPn.del = dlg.prefsPn.add('button',undefined,'Delete Preference');

           

            prefsDrop = dlg.prefsPn.add('dropdownlist',undefined,dropLst);

            prefsDrop.title = 'Load Preferences';           

            prefsDrop.size = [300,25];     

           

        prefsDrop.onChange = function(){

            if(lineType!='Normal Line'){

                dlg.wGp.eTxt.text = xmlPref.prefs.arrows.children()[parseInt(prefsDrop.selection)].width

                dlg.aLgp.ALen.text = xmlPref.prefs.arrows.children()[parseInt(prefsDrop.selection)].leng

                dlg.aWgp.AWid.text = xmlPref.prefs.arrows.children()[parseInt(prefsDrop.selection)].aWidth

                dlg.aConGp.ACon.text = xmlPref.prefs.arrows.children()[parseInt(prefsDrop.selection)].concave

                }

            else{

                dlg.wGp.eTxt.text = xmlPref.prefs.lines.children()[parseInt(prefsDrop.selection)].width

                }

            };

           

        dlg.wGp.eTxt.onChange = function(){

            textToNum (1, 1000, dlg.wGp.eTxt, origLineWidth);

            }

        if(lineType!='Normal Line'){       

            dlg.aLgp.ALen.onChange = function(){

                textToNum (1, 10000, dlg.aLgp.ALen, arrowLengthFactor);

                }      

           

            dlg.aWgp.AWid.onChange = function(){

                textToNum (1, 10000, dlg.aWgp.AWid, arrowWidthFactor);

                }

           

            dlg.aWgp.AWid.onChange = function(){

                textToNum (-50, 50, dlg.aConGp.ACon, arrowConcaveFactor);

                }   

        }//end if

           

            dlg.prefsPn.save.onClick = function(){

                savePrefs ();

                }

           

            dlg.prefsPn.del.onClick = function(){

                if(prefsDrop.selection != null){

                    var selc = parseInt(prefsDrop.selection);                   

                    prefsDrop.remove(selc);

                    if(lineType!='Normal Line'){

                        delete xmlPref.prefs.arrows.children()[selc];

                        }

                    else{

                        delete xmlPref.prefs.lines.children()[selc];

                        }

                    writeXMLFile (xmlFile, xmlPref)

                    }

                }           

           

        dlg.btnGp.okay.onClick = function(){

            dlg.close();

            newWidth = parseInt (dlg.wGp.eTxt.text);

                if(lineType!='Normal Line'){

                arrowLengthFactor = parseInt (dlg.aLgp.ALen.text);

                arrowWidthFactor = parseInt (dlg.aWgp.AWid.text);

                arrowConcaveFactor = parseInt (dlg.aConGp.ACon.text);

                }

            }

       

        dlg.btnGp.cancel.onClick = function(){           

            run = false;

            dlg.close()

            } 

//==================

function savePrefs(){

    var newName = prompt ('Enter New Profile Name', '', 'Save Preferences');

    var prefGood = true;

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

        if(prefsDrop.items.text == newName){

            newName = prompt ('That preset exists\nPlease choose a unique name','', 'Save Preferences' );

            i=0

            }

        }

        prefsDrop.add('item',newName)

        if(lineType=='Normal Line'){

            xmlPref.prefs.lines.appendChild (XML('<line preset="'+ newName+ '"><width>'+dlg.wGp.eTxt.text+'</width></line>'));

            }

        else{  

            xmlPref.prefs.arrows.appendChild (XML('<arrow preset="'+ newName+ '"><width>'+dlg.wGp.eTxt.text+'</width><leng>'+dlg.aLgp.ALen.text+'</leng><aWidth>'+dlg.aWgp.AWid.text+'</aWidth><concave>'+dlg.aConGp.ACon.text+'</concave></arrow>'));

            }

        writeXMLFile (xmlFile, xmlPref)

    }

//=====================       

    dlg.show();

    }

function textToNum(sMin,sMax,e,def){

    def=Math.round (def)

    var sHold = def;

            if(isNaN(parseInt(e.text))){

            alert('"' + e.text + '" is not a number\nEnter a value between ' + sMin + '-' + sMax );

            e.text = def};

            else{

                sHold = parseInt(e.text)

            if(sHold < sMin){

                rangeAlert();

                sHold = sMin;               

                };

            if(sHold > sMax){

                rangeAlert();

                sHold = sMax;

                };

            e.text = sHold;

            }

    function rangeAlert(){alert('Number range must be between ' + sMin + '-' + sMax)};

};//end function textToNum

function getConcaveFactor(x1,y1,x2,y2, x3, y3, x4, y4, x5, y5){//1 & 2 =  shaft pt 1 &2; 3 & 4 = arrow length line; 5 = tail point opp side

    var ptAH = getIntersect (x1, y1, x2, y2, x3, y3, x4, y4);//intersection of shaft with sides of arrowhead

    //mkDot (ptAH)

    var ptTail = getIntersect (x1, y1, x2, y2, x4, y4, x5, y5);//Intersection of arrow tip ends cross shaft

    var conTotalLen = lineL (x1, y1, ptAH[0], ptAH[1]);//gets total length to see if the concave goes in toward the arrowhead or out

    var conFullLen =  lineL (ptTail[0], ptTail[1], ptAH[0], ptAH[1]);//length of arrow from end tips to intersection with shaft

    var conF = lineL (x1, y1, ptTail[0], ptTail[1])/conFullLen

    if(conTotalLen>conFullLen){conF*=-1}

    return Math.round(conF*100)

    }

function getIntersect(x1,y1,x2,y2, x3, y3, x4, y4){

    var slope1 = (y1-y2)/(x1-x2);

    var bIntersect1 = y1-(slope1*x1)

    var slope2 = (y3-y4)/(x3-x4);

    var bIntersect2 = y3-(slope2*x3) 

    var xNew ;

    var yNew;

    if(bIntersect1=='-Infinity'||bIntersect1=='Infinity'){

        xNew=x1;

        yNew = slope2*xNew + bIntersect2;

        }

    else if(bIntersect2=='-Infinity'||bIntersect2=='Infinity'){

        xNew = x3;

        yNew = slope1*xNew + bIntersect1;

        }

    else{

        xNew= (-(bIntersect1-bIntersect2))/(slope1-slope2);

        yNew = slope1*xNew + bIntersect1

        }

   

   

    return [xNew,yNew]

    }

function recordAnchors(pathObj){

    ptArray = new Array();

    for(var i=0;i<pathObj.subPathItems[0].pathPoints.length;i++){

        ptNewArray = ptArray = pathObj.subPathItems[0].pathPoints.anchor;

        }//end loop

    }//end function

function mkNewPathInfo(){

    var pathArray = new Array();

    var piArray = new Array();

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

         piArray = new PathPointInfo;

         piArray.kind = cPath.subPathItems[0].pathPoints.kind;

         piArray.anchor = ptNewArray;

         piArray.leftDirection = ptNewArray;

         piArray.rightDirection = ptNewArray;

        }//end loop

    pathArray[0] = new SubPathInfo();

    pathArray[0].operation = cPath.subPathItems[0].operation;

    pathArray[0].closed = cPath.subPathItems[0].closed;

    pathArray[0].entireSubPath = piArray; 

    return pathArray;

    };//end function

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

    function extractSubPathInfo(pathObj,oldPoint,newPoint){

        var pathArray = new Array();

        var pl = pathObj.subPathItems.length;

        for(var s=0;s<pl;s++){

            var pArray = new Array();

              for(var i=0;i<pathObj.subPathItems.pathPoints.length;i++){

                 pArray = new PathPointInfo;

                 pArray.kind = pathObj.subPathItems.pathPoints.kind;

             if(pathObj.subPathItems.pathPoints.anchor[0]==oldPoint[0] &&

                   pathObj.subPathItems.pathPoints.anchor[1]==oldPoint[1]){

                pArray.anchor = newPoint;

                pArray.leftDirection = newPoint;

                pArray.rightDirection = newPoint;

             }else{

                pArray.anchor = pathObj.subPathItems.pathPoints.anchor;

                pArray.leftDirection = pathObj.subPathItems.pathPoints.leftDirection;

                pArray.rightDirection = pathObj.subPathItems.pathPoints.rightDirection;

             }

              };

            pathArray[pathArray.length] = new Array();

            pathArray[pathArray.length - 1] = new SubPathInfo();

            pathArray[pathArray.length - 1].operation = pathObj.subPathItems.operation;

            pathArray[pathArray.length - 1].closed = pathObj.subPathItems.closed;

            pathArray[pathArray.length - 1].entireSubPath = pArray;

        };

        return pathArray;

    };

       

    function deltPath(){

        var idDlt = charIDToTypeID( "Dlt " );

        var desc2 = new ActionDescriptor();

        var idnull = charIDToTypeID( "null" );

            var ref1 = new ActionReference();

            idPath = charIDToTypeID( "Path" );

            var idvectorMask = stringIDToTypeID( "vectorMask" );

            ref1.putEnumerated( idPath, idPath, idvectorMask );

            var idLyr = charIDToTypeID( "Lyr " );

            var idOrdn = charIDToTypeID( "Ordn" );

            var idTrgt = charIDToTypeID( "Trgt" );

            ref1.putEnumerated( idLyr, idOrdn, idTrgt );

        desc2.putReference( idnull, ref1 );

        executeAction( idDlt, desc2, DialogModes.NO );

        }

   

    function selPath(){

         var idslct = charIDToTypeID( "slct" );

            var desc2 = new ActionDescriptor();

            var idnull = charIDToTypeID( "null" );

                var ref1 = new ActionReference();

                var idPath = charIDToTypeID( "Path" );

                ref1.putName( idPath, "temp" );

            desc2.putReference( idnull, ref1 );

        executeAction( idslct, desc2, DialogModes.NO );      

        }

   

    function mkPath(){

         var idMk = charIDToTypeID( "Mk  " );

            var desc10 = new ActionDescriptor();

            var idnull = charIDToTypeID( "null" );

                var ref3 = new ActionReference();

                var idPath = charIDToTypeID( "Path" );

                ref3.putClass( idPath );

            desc10.putReference( idnull, ref3 );

            var idAt = charIDToTypeID( "At  " );

                var ref4 = new ActionReference();

                var idPath = charIDToTypeID( "Path" );

                var idPath = charIDToTypeID( "Path" );

                var idvectorMask = stringIDToTypeID( "vectorMask" );

                ref4.putEnumerated( idPath, idPath, idvectorMask );

            desc10.putReference( idAt, ref4 );

            var idUsng = charIDToTypeID( "Usng" );

                var ref5 = new ActionReference();

                var idPath = charIDToTypeID( "Path" );

                var idOrdn = charIDToTypeID( "Ordn" );

                var idTrgt = charIDToTypeID( "Trgt" );

                ref5.putEnumerated( idPath, idOrdn, idTrgt );

            desc10.putReference( idUsng, ref5 );

        executeAction( idMk, desc10, DialogModes.NO );      

        }

   

function lineL (ax,ay,bx,by){

    var x = Math.abs (ax-bx);

    var y = Math.abs (ay-by);

    var len = Math.sqrt (Math.pow (x, 2) + Math.pow (y, 2));

    return len

    }

function getAng(ax,ay,bx,by){

    var dx = ax-bx;

    var dy = ay-by;

    var theta = Math.atan2 (dy, dx);

    //theta *= 180/Math.PI

    return theta;

    }

function newPt (x1,y1,rad,ang){

    var newEnd = new Array();

    newEnd[0] = x1 + rad * Math.cos (ang);

    newEnd[1] = y1 + rad * Math.sin (ang);

    return newEnd;

    }

//===============READ/WRITE functions========================================

//=========================================================================

function readXMLFile(file) {

    if (!file.exists) {

        alert( "Cannot find file: " + deodeURI(file.absoluteURI));

        }

    else{

        file.encoding = "UTF8";

        file.lineFeed = "unix";

        file.open("r", "TEXT", "????");

        var str = file.read();

        file.close();

        return new XML(str);

        };

};

function writeXMLFile(file, xml) {

    if (!(xml instanceof XML)) {

        alert( "Bad XML parameter");

        };

    else{

        file.encoding = "UTF8";

        file.open("w", "TEXT", "????");

        //unicode signature, this is UTF16 but will convert to UTF8 "EF BB BF"

        file.write("\uFEFF");

        file.lineFeed = "unix";

        file.write(xml.toXMLString());

        file.close();

        };

    };

//=========================================================================

edwinl35572264
Participant
July 9, 2019

If you're creating a straight line, you're better off using the rectangle shape tool and properties panel to change the width of the shape. Another option is to create the custom shape in Adobe Illustrator, which will allow you to add arrowheads to a stroke and import the vector graphic as a smart object. The smart object will allow you edit the shape in Illustrator and update the PSD layer.

Chuck Uebele
Community Expert
Community Expert
August 31, 2017

I've been playing around with the line tool and attempting to script a solution. The straight line was pretty easy, but the arrow heads are more difficult. Trying to figure out the geometry they used to create the various lengths. Here's what I have so far, the top view is a 40px line changed to a 80px line. the bottom image just shows the new placement of the ends of the arrow head at 80px rather than 40 ps. Just figuring out the arrow's convex feature. Seems to be the length of the line rather than the distance from the base of the arrow. Need to brush up on how to get the intersection between a line and a circle to place those points properly.

c.pfaffenbichler
Community Expert
Community Expert
September 1, 2017

Need to brush up on how to get the intersection between a line and a circle to place those points properly.

Would intersecting two lines not suffice?

Known Participant
September 1, 2017

Hi Chuck, c.pfaffenbichler, Trevor.Dennis, Paul, and Semaphoric,

Thanks for all of your responses.  I never thought this question would have sparked such an in depth discussion.  I greatly appreciate all your help.  My take on this is that the Line tool in Photoshop is not quite as flexible as I would like for annotating photos with arrows (or more specifically, lines with arrowheads).  I appreciate the workarounds that you all have suggested and it looks like I can certainly accomplish what I need/want to do.  This discussion has reminded me (or made me aware), however, that Illustrator might be a more appropriate and flexible tool for this particular task.  I am relatively new to Illustrator (as I am to Photoshop as well) but I will try to learn how to do this in Illustrator.  I will compare it to the suggested photoshop workarounds and decide which tool I prefer.  I am sure I will learn something in the process. 

Thank you all - this forum has been a great resource for me as I am trying to get more comfortable with these Adobe applications.

Best regards,
Paul

Trevor.Dennis
Community Expert
Community Expert
August 31, 2017

Paul, I think I agree with you.  The line tool is a pain in that you can edit after the fact as you can with the other Shape tool. You can Free Transform it, but if you want to keep the arrow head consistent with line width, you then need to use the Direct Selection tool, drag across the relative points, and change them.

So using FT on the upper line increases line width but makes it too long.

You then need to select the Direct Selection tool (white arrow) and drag a window across the end points.

And correct the length thus.  Although what I nearly always do is adjust the width in the Options bar, and make another one.  It is definitely not ideal.

paulwieczorek
Inspiring
August 31, 2017

Thank You sincerely Trevor.Dennis for this thorough explanation, got the point!

What if someone creates a flowchart for example and after finishing the work the decides to change the weight of few lines?

They should not have used the Line Tool but the Pen Tool then, or the Rectangle Tool with its recently introduced »Live Shape Properties«.

Edit: Admittedly having to create the arrowheads separately is inconvenient.

Do You understand we're aware of workarounds, we're aware of Illustrator and such but this is more of a "why they did it this or that way" question?

Quite frankly I doubt the person/s originally responsible for that Tool are still with the Photoshop team so it seems unlikely to get that kind of explanation.

I think the Tool preceded Shape Layers, so it was probably geared at straight pixel or plain path output, live-updating of numeric entries was probably not feasible for these at the time.

Photoshop has several »old« features (the Colour Replacement Tool comes to mind) that I would not recommend to anybody, but removing them might be a problem for the sake of old-time users and possibly because of the code itself.

And now we talk like gentlemans, c.pfaffenbichler​. It's quite strange they (Adobe) have usability problems being a market standard. Especially when most of us got used to strange UI modifications in apps known for years. It's the same kind of issue like in the forums - how one could know the difference between "advanced editor" and "full editor" in new "fast reply" window. I've been using this forums for few years and even to me it was confusing. It's the basics of UX and I'd like to point out that they got Adobe XD app which most of us use everyday for designing a UX It may be the code problem though.

rayek.elfin
Legend
August 31, 2017

paulwieczorek  wrote

It's quite strange they (Adobe) have usability problems being a market standard. Especially when most of us got used to strange UI modifications in apps known for years. It's the same kind of issue like in the forums - how one could know the difference between "advanced editor" and "full editor" in new "fast reply" window. I've been using this forums for few years and even to me it was confusing. It's the basics of UX and I'd like to point out that they got Adobe XD app which most of us use everyday for designing a UX It may be the code problem though.

Photoshop's UI decisions go back to the very beginning - the nineties. Precisely because it *is* the "industry standard" as far as image editors goes, PS suffers from legacy GUI and code base issues that would take a complete re-write in parts to fix properly. Take the pseudo "16bit" mode that is actually a 15bit one, for example, and the image pyramid resulting in banding when zoomed out beyond ~66.67%. Or the one bitmap/one vector mask per layer limitation.

Or in the case of selecting/changing colours when working with shapes and bitmap layers: the regular colour selectors cannot be used with vector shapes, and vice versa. In other image editors any colour selector can be used either for bitmap colours or for vector shapes. Not so in Photoshop: as far as I can see, the vector engine was adapted from elsewhere and bolted on top of Photoshop, rather than integrating it fully. Why else bother users with two separated colour selector GUIs- one for bitmap mode, and one for vector shapes mode? Very, very silly indeed.

It's the same for the line tool: whoever wrote it had to work around the lack of a stroke width implementation at the time. Vectors in Photoshop's code could not be rendered directly to the screen with an arbitrary set width. The simple solution was to create a four-point rectangle. Later the vector engine was bolted on top, and no-one bothered rewriting the code for the line tool and/or made the decision to remove/replace it.

After almost three decades of continuous development Photoshop would benefit from a good cleanup.

Chuck Uebele
Community Expert
Community Expert
August 26, 2017

You can't using the line tool, but you can if you use the pen tool and a single path that can be stroked to the size you want.

Known Participant
August 26, 2017

Thanks Chuck,

If I use the Pen Tool to draw a single (straight) line segment, do you know if there is a way that I can put an Arrowhead at either the Start or the End like I can with the Line Tool?  This is primarily what I use the Line Tool for - drawing arrows to annotate pictures.

It would be nice if I could adjust the Line Weight of these arrows after I drew them, but it is not the end of the world if I had to delete an arrow and draw a new one if I want a different weight.  If using the Pen Tool will make creating arrows more difficult, I'll probably stick with the Line Tool.

Thanks again,
Paul

paulwieczorek
Inspiring
August 30, 2017

First of all, I'd like to admit the issue You're encountering with line weight is the most frustrating and unintuitive option in Photoshop. And I've been Photoshop user for ages (12 or so)...

How the heck one could understand which variable changes the line weight: is it stroke, width or height (these seems to work) or actually weight?

None of them seems to work when You already drew a line. Only height or width if You drew a straight one. On the other hand, weight works perfectly if You set it BEFORE You draw a line - which is stupid because when You want to change existing line, You must draw a new one.