Copy link to clipboard
Copied
Hi, there
I want to make a selection like the one shown in the figure from a pathItem of type "U".
It can be either A or B.
Scripting has limited my ability.
- I deleted two pathPoints but did not get two subPathItems. I can only get one of them.
- I tried to delete a pathPoints that interfered with the makeSelection. It was not possible to delete any pathPoint or make it selected for that purpose.
As a last resort, I'm thinking of getting an array of coordinates of only the pathPoints I need and make a selection. However, this would probably be very time consuming.
I need some ideas.
Thanks in advance.
Translated with [Link removed by moderator] (free version)
Copy link to clipboard
Copied
The image you posted shows vector Paths not selections. You can convert the Paths to selections an file the selections with pixels you could also add a solid fill layer and mask the fill layer with your vector paths. A script can easily do those operations. Adobe Photoshop Scripting DOM does not cover all of Photoshop features some times you need to use Action manager code in Photoshop scripts. But in this case you can set an active selection the has a U shape with DOM code. You are not required to create vector U shape closed paths. You can make selection like your White Areas A and B with a script. You can not EDIT Paths in Photoshop you would need to copy the path to an array modify the points you want to edit then create a new path the path you want.
I do not have the Math knowledge to do curves in paths. Strright point to point selections is more my speed.
Copy link to clipboard
Copied
Hi JJMack, thanks for the response.
The image I posted is just a quick mask, that's my ideal selection. Sorry for the confusion.
First, I have a path item that I called "Original".
I want to make a selection based on this, which can be either A or B, as shown by the white area.
Regards.
Copy link to clipboard
Copied
The paths overlapping Selection A and B were placed by me after the fact, to give an idea of how my ideal selection relates to the shape of the path items.
In order to do this in the script, I thinking I need to remove the inner pathpoints.
I know which pathpoints I need to delete, but I don't know how to delete them.
If I could select any pathpoint, I could delete it, but I can't even select it.
If there is a concrete way to do this that is in line with my idea, I would appreciate it.
Of course, other methods would also be very helpful. However, it needs to be an automatic process.
Copy link to clipboard
Copied
From your Paths you can get the X Y of each control point and use then fot setting selection area create the array for the area you want to select. Like you do using the poly lasso tool.
Select region A then Add to the selection region B
Copy link to clipboard
Copied
JJMack,
Thanks, I'll evaluate it.
Copy link to clipboard
Copied
many thanks JJMack. this post is very informative.
Copy link to clipboard
Copied
The code below would destroy Work Paths, but as long as all Paths are saved it should work here.
One needs to manually select the points-to-be-removed and a temporary Path without those is created and a Selection created from that. (the gif should illustrate)
// create selection from added subpathitems after removing selected pathpoints;
// work path would get destroyed;
// 2021, use it at your own risk;
if (app.documents.length > 0) {
if (app.activeDocument.pathItems.length > 0) {
// collect path;
var path1 = collectselectedPathPathInfoFromDesc ();
if (path1.length > 0) {
// delete;
var iddelete = stringIDToTypeID( "delete" );
executeAction( iddelete, undefined, DialogModes.NO );
// collect edited path;
var path2 = collectselectedPathPathInfoFromDesc ();
// undo;
executeAction( charIDToTypeID("undo"), undefined, DialogModes.NO );
if (path2.length > 0) {
if (path1 != path2) {
// change shape operations;
for (var m = 0; m < path2.length; m++) {
path2[m][path2[m].length-1] = 1097098272
};
// create temp path;
var trashThis = createPath2018(path2, "trashThis");
// make selection;
trashThis.makeSelection(0, true, SelectionType.REPLACE);
// remove temp path;
trashThis.remove();
}
}
}
}
};
////////////////////////////////////
////////////////////////////////////
////////////////////////////////////
////// create a path from collectPathInfoFromDesc2012-array //////
function createPath2018(theArray, thePathsName) {
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.POINTS;
// thanks to xbytor;
cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putProperty(cTID('Path'), cTID('WrPt'));
desc1.putReference(sTID('null'), ref1);
var list1 = new ActionList();
for (var m = 0; m < theArray.length; m++) {
var thisSubPath = theArray[m];
var desc2 = new ActionDescriptor();
desc2.putEnumerated(sTID('shapeOperation'), sTID('shapeOperation'), thisSubPath[thisSubPath.length - 1]);
var list2 = new ActionList();
var desc3 = new ActionDescriptor();
desc3.putBoolean(cTID('Clsp'), thisSubPath[thisSubPath.length - 2]);
var list3 = new ActionList();
for (var n = 0; n < thisSubPath.length - 2; n++) {
var thisPoint = thisSubPath[n];
var desc4 = new ActionDescriptor();
var desc5 = new ActionDescriptor();
desc5.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[0][0]);
desc5.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[0][1]);
desc4.putObject(cTID('Anch'), cTID('Pnt '), desc5);
var desc6 = new ActionDescriptor();
desc6.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[1][0]);
desc6.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[1][1]);
desc4.putObject(cTID('Fwd '), cTID('Pnt '), desc6);
var desc7 = new ActionDescriptor();
desc7.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[2][0]);
desc7.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[2][1]);
desc4.putObject(cTID('Bwd '), cTID('Pnt '), desc7);
desc4.putBoolean(cTID('Smoo'), thisPoint[3]);
list3.putObject(cTID('Pthp'), desc4);
};
desc3.putList(cTID('Pts '), list3);
list2.putObject(cTID('Sbpl'), desc3);
desc2.putList(cTID('SbpL'), list2);
list1.putObject(cTID('PaCm'), desc2);
};
desc1.putList(cTID('T '), list1);
executeAction(cTID('setd'), desc1, DialogModes.NO);
// name work path;
var desc30 = new ActionDescriptor();
var ref6 = new ActionReference();
var idPath = charIDToTypeID( "Path" );
ref6.putClass( idPath );
desc30.putReference( charIDToTypeID( "null" ), ref6 );
var ref7 = new ActionReference();
ref7.putProperty( idPath, charIDToTypeID( "WrPt" ) );
desc30.putReference( charIDToTypeID( "From" ), ref7 );
desc30.putString( charIDToTypeID( "Nm " ), thePathsName );
executeAction( charIDToTypeID( "Mk " ), desc30, DialogModes.NO );
/// get index;
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("itemIndex"));
ref.putEnumerated( charIDToTypeID("Path"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var pathDesc = executeActionGet(ref);
var myPathItem = activeDocument.pathItems[pathDesc.getInteger(stringIDToTypeID("itemIndex")) - 1];
app.preferences.rulerUnits = originalRulerUnits;
return myPathItem
};
////// collect path info from actiondescriptor, smooth added //////
function collectselectedPathPathInfoFromDesc (){
try {
// get index;
var ref = new ActionReference();
ref.putProperty (stringIDToTypeID("property"), stringIDToTypeID("targetPathIndex"));
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var docDesc = executeActionGet(ref);
var theIndex = docDesc.getInteger(stringIDToTypeID("targetPathIndex"))+1;
// collect data;
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.POINTS;
// based of functions from xbytor’s stdlib;
var ref = new ActionReference();
ref.putIndex(cTID("Path"), theIndex);
var desc = app.executeActionGet(ref);
var pname = desc.getString(cTID('PthN'));
// create new array;
var theArray = new Array;
var pathComponents = desc.getObjectValue(cTID("PthC")).getList(sTID('pathComponents'));
// for subpathitems;
for (var m = 0; m < pathComponents.count; m++) {
var listKey = pathComponents.getObjectValue(m).getList(sTID("subpathListKey"));
var operation1 = pathComponents.getObjectValue(m).getEnumerationValue(sTID("shapeOperation"));
switch (operation1) {
case 1097098272:
var operation = 1097098272 //cTID('Add ');
break;
case 1398961266:
var operation = 1398961266 //cTID('Sbtr');
break;
case 1231975538:
var operation = 1231975538 //cTID('Intr');
break;
default:
// case 1102:
var operation = sTID('xor') //ShapeOperation.SHAPEXOR;
break;
};
// for subpathitem’s count;
for (var n = 0; n < listKey.count; n++) {
theArray.push(new Array);
var points = listKey.getObjectValue(n).getList(sTID('points'));
try {var closed = listKey.getObjectValue(n).getBoolean(sTID("closedSubpath"))}
catch (e) {var closed = false};
// for subpathitem’s segment’s number of points;
for (var o = 0; o < points.count; o++) {
var anchorObj = points.getObjectValue(o).getObjectValue(sTID("anchor"));
var anchor = [anchorObj.getUnitDoubleValue(sTID('horizontal')), anchorObj.getUnitDoubleValue(sTID('vertical'))];
var thisPoint = [anchor];
try {
var left = points.getObjectValue(o).getObjectValue(cTID("Fwd "));
var leftDirection = [left.getUnitDoubleValue(sTID('horizontal')), left.getUnitDoubleValue(sTID('vertical'))];
thisPoint.push(leftDirection)
}
catch (e) {
thisPoint.push(anchor)
};
try {
var right = points.getObjectValue(o).getObjectValue(cTID("Bwd "));
var rightDirection = [right.getUnitDoubleValue(sTID('horizontal')), right.getUnitDoubleValue(sTID('vertical'))];
thisPoint.push(rightDirection)
}
catch (e) {
thisPoint.push(anchor)
};
try {
var smoothOr = points.getObjectValue(o).getBoolean(cTID("Smoo"));
thisPoint.push(smoothOr)
}
catch (e) {thisPoint.push(false)};
theArray[theArray.length - 1].push(thisPoint);
};
theArray[theArray.length - 1].push(closed);
theArray[theArray.length - 1].push(operation);
};
};
// by xbytor, thanks to him;
function cTID (s) { return cTID[s] || cTID[s] = app.charIDToTypeID(s); };
function sTID (s) { return sTID[s] || sTID[s] = app.stringIDToTypeID(s); };
// reset;
app.preferences.rulerUnits = originalRulerUnits;
return theArray;
} catch (e) {
return undefined
}
};
Copy link to clipboard
Copied
c.pfaffenbichler,
I'm sorry for the delay in responding. Thank you, that's great technology.
Unfortunately, I can't force the user to choose a point this time. This time the client is not too familiar with photoshop.
A big thank you for your effort and knowledge.
Copy link to clipboard
Copied
Determining the »depression«/»bay« in a subPathItem automatically would seem cumbersome, but not impossible.
Simply using the two highest points would not work reliably because both might be on the same »arm«.
And could there ever be »W«-shapes that have two (or more) »depressions«?
Copy link to clipboard
Copied
Thank you. I'll post an example of a form that is similar to the implemented data.
In fact, it is formed by more than 6,000 pass points. The image has no anch aliasing.
It is said to be a curve representing time and distance.
I am driven by the need to block off the top and bottom of this shape.
This sub-path was created from a selection, as I thought that path items would be better suited for this kind of work than pixels.
Essentially, it would be great if we could accomplish our goal with just the color information and pixels of the selection.
In the future, I plan to look at the positions of the points of the path in turn, and create a function to connect two points where the path is going in opposite directions.
Translated with www.DeepL.com/Translator (free version)
Copy link to clipboard
Copied
What result should that path yield?
Copy link to clipboard
Copied
Ultimately, what I want is a pixels selection. The path is just a means to that end.
Duplicate the background layer with the selection blocking the bay.
Copy link to clipboard
Copied
What result do you want in this case? Please post a screenshot or sketch?
Originally you spoke of »U«-shapes, this shape is very much different …
Copy link to clipboard
Copied
This, this, something else?
Copy link to clipboard
Copied
vertical one.
Copy link to clipboard
Copied
I finally got my script to work properly.
Here's to the forum and the few clues you guys gave me.
pathData = pathData.match(/([\d\.]+ ){2}[mlc]\n|\*U\n/ig); //from Illustrator file..
var spAry = [], ppAry = [], sp, pp;
var dirX = -1, dirY = -1, dirXnew, dirYnew, dirCount = 0, prevPoint, cutPoints = [], cutPoint1, cutPoint2;
for(var i = 0, len = pathData.length; i < len; i++){
if(i % 100 == 0)$.writeln(i);
if(pathData[i].match(/^\*U\n$/)){ //大文字 U でサブパス区切りとする
//谷間うめ
if(cutPoints.length % 2 == 0){
while(cutPoints.length){
cutPoint2 = cutPoints.pop();
cutPoint1 = cutPoints.pop();
ppAry.splice(cutPoint1, cutPoint2 - cutPoint1);
}
}
sp = new SubPathInfo()
sp.operation = ShapeOperation.SHAPEADD;
sp.closed = true;
sp.entireSubPath = ppAry;
spAry.push(sp);
ppAry = [];
cutPoints = [];
dirX = -1;
dirY = -1;
continue;
}
point = pathData[i].match(/[\d\.]+/g);
if(point){
pp = new PathPointInfo();
pp.kind = PointKind.CORNERPOINT;
pp.anchor = [Math.round(point[0] - 0), Math.round(h - point[1])]; //Y座標は反転
pp.leftDirection = pp.anchor;
pp.rightDirection = pp.anchor;
if(ppAry.length){
dirXnew = pp.anchor[0] - prevPoint[0];
dirYnew = pp.anchor[1] - prevPoint[1];
if(dirXnew == 0) dirXnew = dirX;
if(dirYnew == 0) dirYnew = dirY;
dirXnew /= Math.abs(dirXnew);
dirYnew /= Math.abs(dirYnew);
if(dirXnew != dirX || dirYnew != dirY){
dirCount++;
}
if(dirXnew != 0) dirX = dirXnew;
if(dirYnew != 0) dirY = dirYnew;
if(dirCount >= 3){
cutPoints.push(ppAry.length - 1);
dirCount = 0;
}
}
prevPoint = pp.anchor;
ppAry.push(pp);
}
}
//var newpi = doc.pathItems.add("selection", spAry);
add_path("selection", spAry);
var newpi = doc.pathItems.getByName("selection");
newpi.makeSelection(0, false, SelectionType.REPLACE);
Copy link to clipboard
Copied
It would be nicer to post a script that works 😉
Copy link to clipboard
Copied
Sorry, I can't release the whole code I'm writing now because it's NDA-related.
I'll consider it when I'm less busy.
Copy link to clipboard
Copied
What about these areas?
Should they not they also qualify as »indentations«?
Copy link to clipboard
Copied
I also noticed this problem yesterday.
The area will not be processed.
So I am trying to figure out a way to record the points where the path's Y-coordinate switches direction of travel, and then connect the smallest Y-coordinate point with the second, and likewise the largest point with the second.
Copy link to clipboard
Copied
Are there any bezier handles or are all the points just »hard« points?
Copy link to clipboard
Copied
These are all hard points.
I've left out a description of the situation, but it's all consistent with pixels.
I've completed the code since then, but it's in a very dirty format.
I hope to clean it up and publish it someday.
Copy link to clipboard
Copied
Here is a four-point path. Draw a selection you want to get and explain what it is for.
Copy link to clipboard
Copied
In my case, there are no such ambiguous shapes. I use only uniformed lines.
I will complete the function of the script soon.