diff --git a/README.md b/README.md index 03cd6da..2798151 100755 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ Click the links to learn more about the scripts in the selected category. * Rescale * ResizeOnLargerSide * ResizeToSize -* RoundCoordinates +* RoundCoordinates `(upd, 15.03.2022)` ### [Path](md/Path.md) * Points Move Random `(upd, 17.02.2022)` diff --git a/README.ru.md b/README.ru.md index ac51546..7b2d47d 100755 --- a/README.ru.md +++ b/README.ru.md @@ -66,7 +66,7 @@ * Rescale * ResizeOnLargerSide * ResizeToSize -* RoundCoordinates +* RoundCoordinates `(upd, 15.03.2022)` ### [Path](md/Path.ru.md) Скрипты, изменяющие пути. diff --git a/jsx/RoundCoordinates.jsx b/jsx/RoundCoordinates.jsx index b240433..22ca347 100644 --- a/jsx/RoundCoordinates.jsx +++ b/jsx/RoundCoordinates.jsx @@ -10,6 +10,7 @@ 0.1 Initial version 0.2.0 Supports clipping groups, align to reference point 0.2.1 Uses the document ruler mode to get coordinates + 0.3 Added rounding step Donate (optional): If you find this script helpful, you can buy me a coffee @@ -19,7 +20,7 @@ - via PayPal http://www.paypal.me/osokin/usd NOTICE: - Tested with Adobe Illustrator CC 2018-2021 (Mac), 2021 (Win). + Tested with Adobe Illustrator CC 2018-2022 (Mac), 2022 (Win). This script is provided "as is" without warranty of any kind. Free to use, not for sale @@ -34,9 +35,13 @@ app.preferences.setBooleanPreference('ShowExternalJSXWarning', false); // Fix dr $.localize = true; // Enabling automatic localization function main() { - var CFG = { - refPoint: app.preferences.getIntegerPreference('plugin/Transform/AnchorPoint'), - inclStroke: !app.preferences.getBooleanPreference('includeStrokeInBounds'), + var pref = app.preferences, + subdiv = pref.getIntegerPreference('Grid/Horizontal/Ticks'), + grid = pref.getRealPreference('Grid/Horizontal/Spacing'), + CFG = { + step: 1, // Step of coordinates rounding. Set it to zero to read from Preferences > Grid + refPoint: pref.getIntegerPreference('plugin/Transform/AnchorPoint'), + inclStroke: pref.getBooleanPreference('includeStrokeInBounds'), }, LANG = { errDoc: { en: 'Error\nOpen a document and try again', @@ -54,7 +59,7 @@ function main() { return; } - if (!selection.length || selection.typename == 'TextRange') { + if (!selection.length || selection.typename === 'TextRange') { alert(LANG.errSel); return; } @@ -72,17 +77,18 @@ function main() { for (var i = 0, selLen = selection.length; i < selLen; i++) { var currItem = selection[i], - currBoundsPx = getVisibleBounds(currItem, CFG.inclStroke); + boundsPX = getVisibleBounds(currItem, CFG.inclStroke); - for (var j = 0; j < currBoundsPx.length; j++) { - bounds.push(convertUnits(currBoundsPx[j], getDocUnit())); + for (var j = 0; j < boundsPX.length; j++) { + bounds.push(convertUnits(boundsPX[j], getDocUnit())); } - - var delta = getDelta(CFG.refPoint, bounds); + + var step = (CFG.step == 0) ? convertUnits(grid, getDocUnit()) / subdiv : CFG.step, + delta = calcDeltaByAxes(CFG.refPoint, bounds, step); // If has been replaced by the clipping mask bounds - currBoundsPx = CFG.inclStroke ? currItem.visibleBounds : currItem.geometricBounds; - currItem.position = [currBoundsPx[0] + delta.x, currBoundsPx[1] + delta.y]; + boundsPX = currItem.geometricBounds; + currItem.position = [boundsPX[0] + delta.x, boundsPX[1] + delta.y]; bounds = []; // Reset array } @@ -90,61 +96,6 @@ function main() { app.coordinateSystem = defCoordSys; } -// Get the fractional part of the coordinates for the move -function getDelta(point, bounds) { - var x = y = 0, - left = Math.round(bounds[0]) - bounds[0], - right = Math.round(bounds[2]) - bounds[2], - top = Math.round(bounds[1]) - bounds[1], - bottom = Math.round(bounds[3]) - bounds[3] - centerX = bounds[0] + (bounds[2] - bounds[0]) / 2, - centerY = bounds[1] + (bounds[3] - bounds[1]) / 2; - - switch (point) { - case 0: // Left Top - x = left; - y = top; - break; - case 1: // Top Center - x = Math.round(centerX) - centerX; - y = top; - break; - case 2: // Top Right - x = right; - y = top; - break; - case 3: // Left Center - x = left; - y = Math.round(centerY) - centerY; - break; - case 4: // Center Center - x = Math.round(centerX) - centerX; - y = Math.round(centerY) - centerY; - break; - case 5: // Right Center - x = right; - y = Math.round(centerY) - centerY; - break; - case 6: // Left Bottom - x = left; - y = bottom; - break; - case 7: // Center Bottom - x = Math.round(centerX) - centerX; - y = bottom; - break; - case 8: // Bottom Right - x = right; - y = bottom; - break; - } - - x = convertUnits(x + getDocUnit(), 'px'); - y = convertUnits(y + getDocUnit(), 'px'); - - return { 'x': x, 'y': y }; -} - // Get the bounds of the visible content function getVisibleBounds(item, inclStroke) { var childs = []; @@ -217,6 +168,81 @@ function compareBounds(itemBnds, currBnds) { ]; } +// Calculate the delta of the X, Y coordinates for the move +function calcDeltaByAxes(point, bounds, step) { + var x = y = 0, + centerX = bounds[0] + (bounds[2] - bounds[0]) / 2, + centerY = bounds[1] + (bounds[3] - bounds[1]) / 2; + + switch (point) { + case 0: // Left Top + x = getDelta(bounds[0], step); + y = getDelta(bounds[1], step); + break; + case 1: // Top Center + x = getDelta(centerX, step); + y = getDelta(bounds[1], step); + break; + case 2: // Top Right + x = getDelta(bounds[2], step); + y = getDelta(bounds[1], step); + break; + case 3: // Left Center + x = getDelta(bounds[0], step); + y = getDelta(centerY, step); + break; + case 4: // Center Center + x = getDelta(centerX, step); + y = getDelta(centerY, step); + break; + case 5: // Right Center + x = getDelta(bounds[2], step); + y = getDelta(centerY, step); + break; + case 6: // Left Bottom + x = getDelta(bounds[0], step); + y = getDelta(bounds[3], step); + break; + case 7: // Center Bottom + x = getDelta(centerX, step); + y = getDelta(bounds[3], step); + break; + case 8: // Bottom Right + x = getDelta(bounds[2], step); + y = getDelta(bounds[3], step); + break; + } + + x = convertUnits(x + getDocUnit(), 'px'); + y = convertUnits(y + getDocUnit(), 'px'); + + return { 'x': x, 'y': y }; +} + +// Get the delta +function getDelta(n, step) { + var f = Math.round(n) - n; // The fractional digits + return f + (sign(n) * getClosestInt(Math.abs(n), step) - trunc(f + n)); +} + +// Get the closest integer +function getClosestInt(a, b) { + var x = trunc(a / b); + if (!(a % b)) return a; + return (b * (x + 1) - a) < (a - b * x) ? b * (x + 1) : b * x; +} + +// Return the integer part of a number +function trunc(n) { + n = +n; + return (n - n % 1) || (!isFinite(n) || n === 0 ? n : n < 0 ? -0 : 0); +} + +// Return number sign +function sign(n) { + return n ? (n < 0 ? -1 : 1) : 0; +} + // Units conversion function getDocUnit() { var unit = activeDocument.rulerUnits.toString().replace('RulerUnits.', ''); @@ -232,7 +258,7 @@ function getUnits(value, def) { try { return 'px,pt,mm,cm,in,pc'.indexOf(value.slice(-2)) > -1 ? value.slice(-2) : def; } catch (e) {} -}; +} function convertUnits(value, newUnit) { if (value === undefined) return value; diff --git a/md/Item.md b/md/Item.md index b0198cf..1380423 100755 --- a/md/Item.md +++ b/md/Item.md @@ -12,7 +12,7 @@ * Rescale * ResizeOnLargerSide * ResizeToSize -* RoundCoordinates +* RoundCoordinates `(upd, 15.03.2022)` @@ -60,7 +60,7 @@ Adobe Illustrator has a Transform panel, but you cannot use it to transform seve ## RoundCoordinates -The script rounds the coordinates of each selected object. The reference point gets from the `Transform` panel. Works with document units. +The script rounds the coordinates of each selected object. The reference point gets from the `Transform` panel. The script aligns to the stroke if `Preferences > Use Preview Bounds` is enabled. In the script file, you can change the coordinate rounding step in the CFG `step: 1`. If the step is 0, the script aligns to the document grid from `Preferences > Guides & Grid`. ![RoundCoordinates](https://i.ibb.co/3y0WpzC/Round-Coordinates.gif) diff --git a/md/Item.ru.md b/md/Item.ru.md index 2dbae1e..07ec768 100755 --- a/md/Item.ru.md +++ b/md/Item.ru.md @@ -12,7 +12,7 @@ * Rescale * ResizeOnLargerSide * ResizeToSize -* RoundCoordinates +* RoundCoordinates `(upd, 15.03.2022)` @@ -60,7 +60,7 @@ ## RoundCoordinates -Округляет координаты каждого выделенного объекта. Ориентиром для выравнивания будет выбранная контрольная точка из панели `Transform`. Скрипт учитывает единицы измерения документа. +Округляет координаты каждого выделенного объекта. Ориентиром для выравнивания будет выбранная контрольная точка из панели `Transform`. Скрипт учитывает единицы измерения документа и толщину обводки, если включено `Preferences > Use Preview Bounds`. В файле скрипта можно изменить шаг округления координат CFG `step: 1`. Если шаг 0, то скрипт выровняет по сетке документа из `Preferences > Guides & Grid`. ![RoundCoordinates](https://i.ibb.co/3y0WpzC/Round-Coordinates.gif)