在数学中,隐式方程(英语:implicit equation)是形同 f ( a 1 , a 2 , … , a n ) = 0 f(a_1, a_2, \ldots, a_n) = 0 f(a1,a2,…,an)=0
的关系,其中f是多元函数。比如单位圆的隐式方程是 x 2 + y 2 − 1 = 0 x^2 + y^2 - 1 = 0 x2+y2−1=0在这里讨论二元隐式方程,我将使用"隐函数"这个称谓代替"隐式方程".
前言
在中学数学中,我们学过描点法绘制f(x)的图像,即给定x,计算对应的函数值,得到坐标(x1,f(x1)),代入多个x即可得到多个该函数上的点,再把这些点依次相连即可画出函数大致图像,当x取值的间隔(步长)越小时,绘制的图像越接近真实图像.
在计算机中函数绘图也是应用这种思想,计算的都是离散的值,连续值是不可能实现的.
对于显函数y=f(x),直接把x代入计算即可得到函数上某点的坐标.但是对于隐式方程,如 sin ( x + y ) − cos ( x y ) = sin ( x ) \sin(x+y) - \cos(xy) = \sin(x) sin(x+y)−cos(xy)=sin(x)显然无法直接代入x然后得到y.
这时候一般有两种方法:
- 反解出y,写成显函数.这种方法显然对于计算机是困难的.
- 暴力代值,把x和y的所有取值都代入方程,当方程两边先等时得解.这种方法耗时但是可行,还有就是误差/精度问题,实数是无穷个的,实际操作可能是在x∈[a,b],y∈[c,d],上进行计算,并且取一个步长0.1或者更小,也就是无法取到每一个值,多数情况下方程的等号不会成立,因为有误差,此时需要设置一个误差容限,只要小于这个误差就认为方程成立.
我使用的是方法2的思想,并且对隐式方程要先进行变形,移项成f(x,y)=…=0的形式.目的是用f(x,y)的值判断当前代入点与真实方程上的点的关系.下图是之前做的,现在看来可能存在一些错误,主要是为了了解为什么要变形成f(x,y)=0.
接下来就是考虑坐标的问题了,计算机画布的坐标和函数的平面直角坐标.具体就不赘述了,我之前是在函数坐标上对x和y进行采样,然后再映射到画布坐标,这样做的弊端就是当步长比较大的时候,绘制出来的图像是离散的.从简单的$ y=x^2 $去理解,在x正方向上,等步长取x,对应的y其实是越来越大的(增量越来越大),为了削弱这种影响,只能把步长取小,但是这样无法从根本解决问题,并且会增加计算量
tanx,步长0.01
tanx,步长0.001
为了彻底解决这个问题,这次我将直接使用画布的坐标系统,画图的本质就是像素点上颜色的填充,直接判断这个像素点是否要填充(像素点内有解).
像素
像素可以是长方形的或者方形的。有一个数称为长宽比,用于表述像素有多方。例如1.25:1的长宽比表示每个像素的宽是其高度的1.25倍。电脑屏幕上的像素通常是方的.维基百科
Windows 窗体(其他基本上也是这样)的坐标系统基于设备坐标,在 Windows 窗体中绘制时的基本度量单位是设备单元(通常是像素)。屏幕上的点由 x 和 y 坐标对描述,x 坐标向右递增,y 坐标从上到下递增。Microsoft Learn
实际坐标应该是这样的
但我们需要这种
在线例子
使用js简单实现了一下,很多逻辑和算法还没写,主要是为了验证可行性和计算速度.目前是能流畅地拖动显示范围和放缩视角.代码比较简单,想尝试的可以访问隐函数绘图.
目前还有很多已知的bug.