另一个属性:levelstep=2到此,我们先整理一下已知信息:
- 表示每一层与相邻一层的比为 2
- 瓦片图的大小为512x512,但最后一行或者每行的最后一列可能不是512
- 最高层级分辨率 = 全景图 / 3.125
- 每一层级的分辨率与相邻层级的比为 2
每一层级的宽度 % 512 % 64 = 0经过验证,krpano所有切图都满足这样的条件 。
如果余数不为零,那咋办?同样经过大量样本推算,如果余数小于64,则舍弃,即当前层级的分辨率要减去这个余数,如果余数大于64,则相加 。
这时候我简单写一条算法来计算一下我的猜想:
// 设全景图大小为10000x5000const panoSize = 10000// 系数,瓦片图最高层级的尺寸 = 图片宽度 / 系数const coefficient = 3.125// 瓦片图最大尺寸const maxTileSize = 512// 瓦片图最小尺寸const minTileSize = 64// 相邻层级的比const levelstep = 2// 调整层级的尺寸:控制 faceSize % 512 % 64 = 0function adjustLevelSize(inputLevelSize: number) {if (inputLevelSize % maxTileSize % minTileSize === 0) return inputLevelSizeconst lastTileSize = inputLevelSize % maxTileSize// 最后一行小于64则舍弃if (lastTileSize < minTileSize) {inputLevelSize -= lastTileSize} else {//最后一行瓦片的余数(对64取余)const minRemainder = lastTileSize % minTileSizeif (minRemainder !== 0) {inputLevelSize = inputLevelSize - (minTileSize - minRemainder)}}return inputLevelSize}// 最高层级(余数为0)let levelSize1 = panoSize / coefficient // levelSize1 = 3200levelSize1 = adjustLevelSize(levelSize1) // levelSize1 = 3200// 下一级(余数为0)let levelSize2 = levelSize1 / levelstep // levelSize2 = 1600levelSize2 = adjustLevelSize(levelSize2) // levelSize2 = 1600// 下一级(余数为32,800 % 512 % 64 = 32,舍弃,故levelSize3 = 800 - 32 = 768)let levelSize3 = levelSize2 / levelstep // levelSize3 = 800levelSize3 = adjustLevelSize(levelSize3) // levelSize3 = 768...// 官方1万-1.5万像素的,只有三个层级,故切到第三层,那我就不能再切了,我得找出最低层级的最小分辨率 。通过以上的计算,同一张全景图我的算法与krpano切图进行对比:level我的算法krpano算法3320032002160016641768768第二层级虽然有64像素的差距,但是我遵循的是层级比为2,krpano第二层级偶尔会略大或者略小,其实这是动态计算的,前面也有讲,几乎约等于2,在正常波动内,所以这没问题 。
2万px以内的全景图,每隔1000px我都测试一下,发现没有问题,完全可用 。
04.最终算法实现
analyzeImageLevel(panoWidth: number) {// 系数,瓦片图最高层级的尺寸 = 图片宽度 / 系数const coefficient = 3.125// 瓦片图最大尺寸const maxTileSize = 512// 瓦片图最小尺寸const minTileSize = 64// 调整层级的尺寸:控制 faceSize % 512 % 64 = 0function adjustLevelSize(inputLevelSize: number) {if (inputLevelSize % maxTileSize % minTileSize === 0) return inputLevelSizeconst lastTileSize = inputLevelSize % maxTileSize// 最后一行小于64则舍弃if (lastTileSize < minTileSize) {inputLevelSize -= lastTileSize} else {//最后一行瓦片的余数(对64取余)const minRemainder = lastTileSize % minTileSizeif (minRemainder !== 0) {inputLevelSize = inputLevelSize - (minTileSize - minRemainder)}}return inputLevelSize}function getLevelConfig(panoSize): ILevelConfig[] {let count = 1let levels = []const minFaceSize = 640const topLevelSize = panoSize / coefficient// 最高层levels.push({level: count,size: adjustLevelSize(topLevelSize)})getNextLevelConfig(topLevelSize)// 递归获取子层级function getNextLevelConfig(topLevelSize) {const levelstep = 2const nextLevelSize = topLevelSize / levelstepif (nextLevelSize + minTileSize >= minFaceSize) {count++levels.push({level: count,size: adjustLevelSize(nextLevelSize)})getNextLevelConfig(nextLevelSize)}}// 层级转为正常从小到大levels = levels.map((item, index) => {item.level = levels.length - indexreturn item})return levels}this.levelConfig = getLevelConfig(panoWidth)}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
