Dart实现Minecraft椭圆绘制:优化圆润度的数学问题求助
Minecraft椭圆绘制工具优化方案
问题分析
你当前的Dart代码生成的椭圆行激活块数为(8, 10, 10, 10, 10, 10, 10, 10, 10, 8),核心问题是只要点在椭圆内部就标记为激活,导致中间大部分行直接铺满整个宽度,边缘收缩过于突兀。需要调整数学逻辑,让激活块数从边缘到中心逐渐递增,实现(4, 6, 8, 10, 10, 10, 10, 8, 6, 4)的圆润渐变效果。
优化后的代码
替换原类中的blocks getter方法:
List<List<bool>> get blocks { final blocks = List.generate(depth, (_) => List.filled(width, false)); final a = width / 2.0; // 半长轴 final b = depth / 2.0; // 半短轴 final centerX = a; final centerY = b; // 边缘收缩系数:0~1之间,值越小边缘收缩越明显,可根据需求调整 const edgeShrinkFactor = 0.6; for (int y = 0; y < depth; y++) { // 计算当前行到椭圆中心的归一化纵向距离 final normalizedY = (y - centerY) / b; final ySquared = normalizedY * normalizedY; // 计算椭圆方程中当前行对应的横向半径平方 final xRadiusSquared = 1 - ySquared; if (xRadiusSquared <= 0) continue; // 超出椭圆范围,无激活块 // 调整横向半径,让边缘行宽度随纵向距离增加而平滑收缩 final adjustedXRadius = sqrt(xRadiusSquared) * (1 - (1 - edgeShrinkFactor) * ySquared); final halfWidth = adjustedXRadius * a; // 计算当前行激活块的起始/结束x坐标 final startX = (centerX - halfWidth).round(); final endX = (centerX + halfWidth).round(); // 确保坐标在有效范围内 final actualStartX = max(0, startX); final actualEndX = min(width - 1, endX); // 标记当前行的激活块 for (int x = actualStartX; x <= actualEndX; x++) { blocks[y][x] = true; } } return blocks; }
关键优化点
- 移除冗余对称赋值:原代码中重复设置四个对称点的逻辑会导致重复赋值,改为逐行计算激活范围,逻辑更清晰且高效。
- 平滑收缩逻辑:通过
edgeShrinkFactor控制边缘收缩程度,结合椭圆方程调整每行的横向激活范围,让边缘行的宽度随纵向距离平滑递减。 - 边界安全处理:使用
max()/min()确保x坐标在0到width-1之间,避免数组越界错误。
效果调整
- 若想要更明显的边缘收缩,可降低
edgeShrinkFactor(比如设为0.4); - 若想要接近原椭圆效果,可提高
edgeShrinkFactor(比如设为0.9)。
内容的提问来源于stack exchange,提问作者FMorschel
相关产品推荐
相关产品推荐

