Morton Code排序致坐标异常:4x4瓦片拼接Y轴偏移求助
问题分析与修复方案
你的代码核心问题在于多余且错误的Morton编码→解码流程:你先将线性索引fileIdx转换为网格坐标x,y,接着把x,y编码为Morton ID,随后又用错误的方式(取模/除法)解码回坐标,这完全是画蛇添足,且解码逻辑完全不符合Morton码的规则,直接导致了Y轴偏移。
具体错误点
- 浮点数问题:
y = fileIdx / scale在JavaScript中会返回浮点数(比如fileIdx=5时y=1.25),后续位运算会强制转整数,但错误解码时又用浮点数除法,进一步放大偏移。 - 错误的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
相关产品推荐
相关产品推荐

