You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Morton Code排序致坐标异常:4x4瓦片拼接Y轴偏移求助

问题分析与修复方案

你的代码核心问题在于多余且错误的Morton编码→解码流程:你先将线性索引fileIdx转换为网格坐标x,y,接着把x,y编码为Morton ID,随后又用错误的方式(取模/除法)解码回坐标,这完全是画蛇添足,且解码逻辑完全不符合Morton码的规则,直接导致了Y轴偏移。

具体错误点

  1. 浮点数问题:y = fileIdx / scale在JavaScript中会返回浮点数(比如fileIdx=5时y=1.25),后续位运算会强制转整数,但错误解码时又用浮点数除法,进一步放大偏移。
  2. 错误的Morton解码:x = (id % scale) * 256和y = (id / scale) * 256完全不是Morton码的解码方式——Morton码是将x、y的二进制位交错存储,解码需要提取奇偶位,而非简单的取模/除法。比如fileIdx=2(x=2,y=0)编码后得到的Morton ID是4,4%4=0会把x错误计算为0,直接导致位置偏移。

修复方案

既然你的文件是按线性顺序(行优先)排列的,完全不需要Morton编码流程,直接用fileIdx计算网格坐标即可:

var fileDirectory = Folder.selectDialog("Select a folder");
var files = fileDirectory.getFiles("*.png");
var activeDoc = app.activeDocument;
var scale = 4;

for (var fileIdx = 0; fileIdx < files.length; fileIdx++)
{
   app.load(files[fileIdx]);
   backFile = app.activeDocument;
   backFile.selection.selectAll();
   backFile.selection.copy();
   backFile.close(SaveOptions.DONOTSAVECHANGES);
   activeDoc.paste();
   activeDoc.activeLayer.name = fileIdx;
   
   // 直接计算网格坐标,用Math.floor确保y是整数
   var x = fileIdx % scale;
   var y = Math.floor(fileIdx / scale);
   
   // 计算最终位置(假设每个瓦片256px)
   x = x * 256;
   y = y * 256;
   
   var LB = activeDoc.activeLayer.bounds;
   activeDoc.activeLayer.translate(-LB[0].as('px') + new UnitValue(x, 'px'), -LB[1].as('px') + new UnitValue(y, 'px'));
}

如果确实需要处理Morton顺序的文件

若你的文件是按Morton ID命名的(而非线性顺序),则保留编码逻辑,替换为正确的解码函数:

var fileDirectory = Folder.selectDialog("Select a folder");
var files = fileDirectory.getFiles("*.png");
var activeDoc = app.activeDocument;
var scale = 4;

var MASKS = [0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF];
var SHIFTS = [1, 2, 4, 8];

// 正确的Morton解码函数
function decodeMortonX(id) {
  id = id & MASKS[0];
  id = (id | (id >> SHIFTS[0])) & MASKS[1];
  id = (id | (id >> SHIFTS[1])) & MASKS[2];
  id = (id | (id >> SHIFTS[2])) & MASKS[3];
  id = (id | (id >> SHIFTS[3])) & 0x0000FFFF;
  return id;
}

function decodeMortonY(id) {
  id = (id >> 1) & MASKS[0];
  id = (id | (id >> SHIFTS[0])) & MASKS[1];
  id = (id | (id >> SHIFTS[1])) & MASKS[2];
  id = (id | (id >> SHIFTS[2])) & MASKS[3];
  id = (id | (id >> SHIFTS[3])) & 0x0000FFFF;
  return id;
}

for (var fileIdx = 0; fileIdx < files.length; fileIdx++)
{
   app.load(files[fileIdx]);
   backFile = app.activeDocument;
   backFile.selection.selectAll();
   backFile.selection.copy();
   backFile.close(SaveOptions.DONOTSAVECHANGES);
   activeDoc.paste();
   activeDoc.activeLayer.name = fileIdx;
   
   // 假设fileIdx就是Morton ID,或者从文件名提取ID
   var id = fileIdx;
   var x = decodeMortonX(id);
   var y = decodeMortonY(id);
   
   x = x * 256;
   y = y * 256;
   
   var LB = activeDoc.activeLayer.bounds;
   activeDoc.activeLayer.translate(-LB[0].as('px') + new UnitValue(x, 'px'), -LB[1].as('px') + new UnitValue(y, 'px'));
}

内容的提问来源于stack exchange,提问作者guiguig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 03:41:44