Last active
September 17, 2023 06:16
-
-
Save moluapple/94aaf66070f618641a8a4d34bfb8d4bf to your computer and use it in GitHub Desktop.
[Illustrator] 寻找不规则形状中心点(find visual center of an irregularly shaped polygon with Illustrator)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
var doc = app.activeDocument, | |
lays = doc.layers, | |
WORK_LAY = lays.add(), | |
NUM_LAY = lays.add(), | |
i = lays.length - 1, | |
lay; | |
// main working loop | |
for (; i > 1; i--) { | |
//process each layer | |
lay = lays[i]; | |
lay.name = lay.name + " Num:" + (i - 1); // i-1 as 2 layers beed added. | |
process(lay.pathItems, false); | |
process(lay.compoundPathItems, true); // if any | |
} | |
//clean up | |
NUM_LAY.name = "Numbers"; | |
WORK_LAY.remove(); | |
function process(items, isCompound) { | |
var j = 0, | |
b, xy, s, p, op; | |
for (; j < items.length; j++) { | |
// process each pathItem | |
op = items[j]; | |
// add stroke | |
if (isCompound) { | |
strokeComPath(op); | |
} else { | |
!op.closed && op.closed = true; | |
op.filled = false; | |
op.stroked = true; | |
}; | |
b = getCenterBounds(op); | |
xy = [b[0] + (b[2] - b[0]) / 2, b[1] + (b[3] - b[1]) / 2]; | |
s = ( | |
Math.min(op.height, op.width) < 20 || | |
(op.area && Math.abs(op.area) < 150) | |
) ? 4 : 6; // adjust font size for small area paths. | |
add_nums(i - 1, xy, s); | |
} | |
} | |
function getMinVisibleSize(b) { | |
var s = Math.min(b[2] - b[0], b[1] - b[3]); | |
return Math.abs(s); | |
} | |
function getGeometricCenter(p) { | |
var b = p.geometricBounds; | |
return [(b[0] + b[2]) / 2, (b[1] + b[3]) / 2]; | |
} | |
// returns square of distance between p1 and p2 | |
function getDist2(p1, p2) { | |
return Math.pow(p1[0] + p2[0], 2) + Math.pow(p1[1] + p2[1], 2); | |
} | |
// returns visibleBounds of a path in a compoundPath p | |
// which is closest to center of the original path op | |
function findBestBounds(op, p) { | |
var opc = getGeometricCenter(op); | |
var idx = 0, | |
d; | |
var minD = getDist2(opc, getGeometricCenter(p.pathItems[0])); | |
for (var i = 0, iEnd = p.pathItems.length; i < iEnd; i++) { | |
d = getDist2(opc, getGeometricCenter(p.pathItems[i])); | |
if (d < minD) { | |
minD = d; | |
idx = i; | |
} | |
} | |
return p.pathItems[idx].visibleBounds; | |
} | |
function applyOffset(op, checkBounds) { | |
var p = op.duplicate(WORK_LAY, ElementPlacement.PLACEATBEGINNING), | |
// offset value the small the better, but meantime more slow. | |
offset = function() { | |
var minsize = Math.min(p.width, p.height); | |
if (minsize >= 50) { | |
return '-1' | |
} else if (20 < minsize && minsize < 50) { | |
return '-0.5' | |
} else { | |
return '-0.2' // 0.2 * 2 (both side ) * 50 (Times) = 20 | |
} | |
}, | |
xmlstring = '<LiveEffect name="Adobe Offset Path"><Dict data="I jntp 2 R mlim 4 R ofst #offset"/></LiveEffect>' | |
.replace('#offset', offset()), | |
TIMES = 100; // if shapes are too large, should increase the value. | |
if (checkBounds) { | |
// check its size only if it needs, because it's too slow | |
while (TIMES-- && getMinVisibleSize(p.visibleBounds) > 3) p.applyEffect(xmlstring); | |
} else { | |
while (TIMES--) p.applyEffect(xmlstring); | |
} | |
return p; | |
} | |
function getCenterBounds(op) { | |
var originalMinSize = getMinVisibleSize(op.visibleBounds); | |
var p = applyOffset(op, false); | |
if (getMinVisibleSize(p.visibleBounds) > originalMinSize) { | |
// in some cases, path p becomes larger for some unknown reason | |
p.remove(); | |
p = applyOffset(op, true); | |
} | |
var b = p.visibleBounds; | |
if (getMinVisibleSize(b) > 10) { | |
activeDocument.selection = [p]; | |
executeMenuCommand("expandStyle"); | |
p = activeDocument.selection[0]; | |
if (p.typename == "CompoundPathItem") { | |
b = findBestBounds(op, p); | |
} | |
} | |
p.remove(); | |
return b; | |
} | |
function add_nums(n, xy, s) { | |
var txt = NUM_LAY.textFrames.add(); | |
txt.contents = n; | |
txt.textRange.justification = Justification.CENTER; | |
txt.textRange.characterAttributes.size = s; | |
txt.position = [xy[0] - txt.width / 2, xy[1] + txt.height / 2]; | |
} | |
function strokeComPath(compoundPath) { | |
var p = compoundPath.pathItems, | |
l = p.length, | |
i = 0; | |
for (; i < l; i++) { | |
!p[i].closed && p[i].closed = true; | |
p[i].stroked = true; | |
p[i].filled = false; | |
}; | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@shspage hello, I tried it but lay.pathItems.length is always 0, why?