圆锥曲线绘制

二次曲线:

\[Ax^2+Bxy+cy^2+Dx+Ey+F=0 \]

可以表示圆弧,椭圆,抛物线。它们的绘制是使用离散的小直线段来逼近理想曲线。

1 绘制整圆的Bresenham算法

  • 八路对称
  • 只计算 45度至90度范围内的点
  • 移动方向为+x,-y

当前画的点为\(P(x_i, y_i)\), 下一个点可以是 \(T(x_i+1,y_i)\)\(S(x_i+1,y_i-1)\)

image-20211122114630254

D(T)为T点到原点距离的平方与半径的平方之差,D(S)为S点到原点距离与半径平方之差

则:

\[D(T)=(x_i+1)^2 + (y_i)^2 - r^2 \\ D(S)=(x_i+1)^2 + (y_i-1)^2 - r^2 \]

因为 D(T) > 0, D(S) < 0,令变量 \(d_i= D(T) + D(S)\)

则:

\[d_i = 2(x_i+1)^2 + y_i^2 + (y_i-1)^2 - 2r^2 \]

\(d_i<0\), 有 \(|D(T)| < |D(S)|\), 选择像素 \(T\)。否则选择像素 \(S\)

截屏2021-11-22 上午11.51.45

2 角度离散法绘制圆弧和椭圆弧

input:圆心坐标\((x_c, y_c)\) 半径 \(r\),则以角度 \(t\) 为参数的圆的参数方程为:

\[x = x_c + r\cos t y = y_c + r\sin t \]

  • 借助参数方程绘制曲线的方法都是将圆弧离散化为短直线段,该方法的好处是:无需处理孤立的像素点,而是转化为直线绘制算法来控制
void Arc(int xc, int yc, double r, double ts, double te){
  double pi = 3.1415926;
  if (te < ts){
    te += 2 * pi;
  }
  
  double dt = 0.4 / r; // 角度的离散值, 使其与半径成反比
  int n = (int)( (te-ts)/dt + 0.5 ); // 确定总步数, 0.5 是四舍五入
  double ta = ts;
  int x = xc + int(r * cos(ts));
  int y = yc + int(r * sin(ts));
  
  MoveTo(x, y); // 画笔移到初始点 (x,y) 处
  for(int i = 1; i <= n; ++i){
    ta += dt;
    double cost = cos(ta);
    double sint = sin(ta);
    x = int(xc + r * cost);
    y = int(yc + r * sint);
    LineTo(x, y); // 当前画笔位置与 (x,y) 连一条线, 然后将画笔位置移动到 (x,y)
  }
  
}

3 椭圆的扫描转换算法

截屏2021-11-22 下午2.56.14 截屏2021-11-22 下午4.33.57

截屏2021-11-22 下午4.35.36 截屏2021-11-22 下午4.36.16
posted @ 2021-11-22 16:43  popozyl  阅读(350)  评论(0编辑  收藏  举报