Skip to main content
Participant
May 19, 2025
Answered

Finding the position of pathItems AND compoundPathItems

  • May 19, 2025
  • 1 reply
  • 311 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
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.

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
Community Expert
jduncanCommunity ExpertCorrect 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.");