Skip to main content
New Participant
May 19, 2025
Answered

Finding the position of pathItems AND compoundPathItems

  • May 19, 2025
  • 1 reply
  • 294 views

I can find the location of ‘pathItems’ and I can find the location of ‘compoundPathItems’, but how do I combine the two scripts so I get the location of all the pathItems and all the compoundPathItems in one script??

I am sharing a highly reduced version of the relevant part of my code. I will not be using alert(), but that’s another story.

// SCRIPT 1
function getTopLeft() {
for (var i = 0; i < app.activeDocument.pathItems.length; i++) {

    var foo = app.activeDocument.pathItems[i].position[0];

    alert(foo);

}
}


getTopLeft();





// SCRIPT 2
function getTopLeft() {
for (var i = 0; i < app.activeDocument.compoundPathItems.length; i++) {

    var foo = app.activeDocument.compoundPathItems[i].position[0];

    alert(foo);

}
}


getTopLeft();
Correct answer jduncan

So, if you just want the paths that are not part of a compound path and compound paths, try the code below. It iterates over every page item, if the page item is a compound path, it gets added to the final array, and if it is a regular pathItem, a separate checker function is called that checks inside of every document compound path to see if the path is a child. I'm sure there are some deeply nested clipping masks/compound paths that will break this code but it works for the few simple tests I had time to run it on. Cheers!

 

var doc = app.activeDocument;

// check to see if a path is part of a compound path
function parentIsCompoundPath(pathItem) {
    for (var i = 0; i < doc.compoundPathItems.length; i++) {
        for (var j = 0; j < doc.compoundPathItems[i].pathItems.length; j++) {
            if (pathItem === doc.compoundPathItems[i].pathItems[j]) return true;
        }
    }
    return false;
}

var allPathItems = [];
for (var i = 0; i < doc.pageItems.length; i++) {
    if (doc.pageItems[i].typename == "CompoundPathItem") {
        allPathItems.push(doc.pageItems[i]);
    } else if (doc.pageItems[i].typename == "PathItem") {
        if (!parentIsCompoundPath(doc.pageItems[i])) {
            allPathItems.push(doc.pageItems[i]);
        }
    }
}

alert("Found " + allPathItems.length + " 'path type' items.");

 

1 reply

jduncan
Community Expert
May 19, 2025

If your artwork isn't too crazy complex, you can simply iterate over all of the documents page items and pull out any with a type of `pathItem` or `compoundPathItem` like below.

 

var doc = app.activeDocument;

var allPathItems = [];

for (var i = 0; i < doc.pageItems.length; i++) {
    if (
        doc.pageItems[i].typename == "PathItem" ||
        doc.pageItems[i].typename == "CompoundPathItem"
    ) {
        allPathItems.push(doc.pageItems[i]);
    }
}

alert("Found " + allPathItems.length + " 'path type' items.");

 

If your artwork is very complex and has many other `pageItem` types othan than the two you are trying to target, you could also do two loops, one for `pathItems` and one for `compoundPathItems` and push everything into a single array before doing whatever work you need to do.

New Participant
May 19, 2025

Excellent, thank you. Your solution does what I asked but because paths contained within a compound path are returned as individual paths, I am getting more than I want.

compo 284 114 338 168 284 114 pat 104 69

'compo' is a composite path made from two paths, so I am getting the location of the composite path and the location of the paths contained within the composite path.

Here is my script as it stands:

var doc = app.activeDocument;

var allPathItems = [];

logInfo((new Date).toString());
logInfo(" ");


for (var i = 0; i < doc.pageItems.length; i++) {
    if (
        doc.pageItems[i].typename == "PathItem" ||
        doc.pageItems[i].typename == "CompoundPathItem"
    ) {
        allPathItems.push(doc.pageItems[i]);
    }
}

alert("Found " + allPathItems.length + " 'path type' items.");

for (var j = 0; j < allPathItems.length; j++) {

    var foo = allPathItems[j].position[0];
    var goo = -1 * allPathItems[j].position[1];
    var hoo = allPathItems[j].name;
    
    logInfo(String(hoo)+" "+String(foo)+" "+String(goo));

}


function logInfo(Txt){
var file = new File(Folder.desktop + "/reports/simple6.txt");
file.open("a", "TEXT", "????");
file.seek(0,2);
$.os.search(/windows/i)  != -1 ? file.lineFeed = 'windows'  : file.lineFeed = 'macintosh';
file.writeln(Txt);
file.close();
};
jduncan
jduncanCorrect answer
Community Expert
May 19, 2025

So, if you just want the paths that are not part of a compound path and compound paths, try the code below. It iterates over every page item, if the page item is a compound path, it gets added to the final array, and if it is a regular pathItem, a separate checker function is called that checks inside of every document compound path to see if the path is a child. I'm sure there are some deeply nested clipping masks/compound paths that will break this code but it works for the few simple tests I had time to run it on. Cheers!

 

var doc = app.activeDocument;

// check to see if a path is part of a compound path
function parentIsCompoundPath(pathItem) {
    for (var i = 0; i < doc.compoundPathItems.length; i++) {
        for (var j = 0; j < doc.compoundPathItems[i].pathItems.length; j++) {
            if (pathItem === doc.compoundPathItems[i].pathItems[j]) return true;
        }
    }
    return false;
}

var allPathItems = [];
for (var i = 0; i < doc.pageItems.length; i++) {
    if (doc.pageItems[i].typename == "CompoundPathItem") {
        allPathItems.push(doc.pageItems[i]);
    } else if (doc.pageItems[i].typename == "PathItem") {
        if (!parentIsCompoundPath(doc.pageItems[i])) {
            allPathItems.push(doc.pageItems[i]);
        }
    }
}

alert("Found " + allPathItems.length + " 'path type' items.");