在本文中,将探讨一种新颖的算法,它利用整数运算来处理3D数学函数,特别适用于CNC机器和3D打印机。这种算法不仅简化了计算过程,还避免了浮点数的使用和复杂操作,从而提高了效率和精确度。
算法的核心思想是利用像素化世界的特性,即在绘制连续函数的下一个点时,候选点仅限于相邻的像素。这样,只需要考虑8个相邻像素,再加上前一个点的取向,候选点的数量可以减少到5个。通过计算这5个候选点的函数值,选择最佳点,并重复此过程,直到曲线的终点。
与传统数学不同,这种算法只关注模糊误差,这简化了公式,避免了浮点数的使用和复杂操作。例如,在计算圆的下一个点时,只需计算每个候选点的误差:
error ~= x*x + y*y - r*r
其中x和y是候选点的坐标,r是圆的半径。这意味着每个候选点需要进行三次乘法和两次整数加法,最重要的是,它避免了开方和除法。
在经典数学中,如圆或线这样的函数由满足特定限制的无限点集组成,它们是笛卡尔平面的子集,甚至可能由多个实体组成。相比之下,光栅化函数是完全不同的,它是一组有限的点,这些点彼此相关,最重要的是顺序。
演示器是一个code::blocks项目,由于没有依赖项,提供了64位的可执行文件。它能够绘制线条和圆,扩展到其他基本图形也很简单。只有三个文件,所以移植到另一个IDE可能很容易。
使用键盘操作,有简短的帮助。在屏幕左下角,算法相关的9个像素以3x3网格的形式出现,对于每个计算的像素(每次迭代计算5个),函数的误差会出现。系统将选择误差最低的点作为下一个点。
以下是圆的基本图形,其中心相对于当前点:
int circleGuess(int *center, int x, int y) {
x -= center[0];
y -= center[1];
return (x*x + y*y - (center[0] * center[0]) - (center[1] * center[1]));
}
每次调用nextPoint时,ptCur将被更新:
int params[2] = {x, y};
ptCur = nextPoint(circleGuess, params, ptCur.heading, ptCur.x, ptCur.y);
这是事件驱动的编程,因此可读性较差。然而,添加新的图形很容易。第一个参数是一个包含函数所需参数的指针(二次贝塞尔曲线需要的参数比圆多),剩下的两个参数是测试点。
在3D版本中,事情变得更加复杂。2D版本中使用的3x3像素正方形变成了3x3x3的“魔方”,导航以获取下一个点必须考虑更多的选项。然而,留下了功能代码,以便可以包含在内。
这种算法确实有效,已经在stm32 nucleo上进行了测试。未来,这种算法可以简化CNC路由器上旋转工具的使用,以及屏幕渲染的“廉价”抗锯齿。