写在前面
由于文章中公式与代码较多,所以字符数较多,超过了上限。需要拆成多个part。共3个part:直线与曲线绘制、图形的变换、杂项。
1.生成直线的Bresenham算法
deltax=x2-x1; deltay=y2-y1; k=deltay/deltax; e=k-0.5; x=x1; y=y1; for (;x<=x2;x++){ putpixel(x,y,pixelcolor); if (e<0) e=e+k; else{ y=y+1; e=e+k-1; } }
deltax=x2-x1; deltay=y2-y1; k=deltax/deltay; e=k-0.5; x=x1; y=y1; for (;y<=y2;y++){ putpixel(x,y,pixelcolor); if (e<0) e=e+k; else{ x=x+1; e=e+k-1; } }
deltax=x2-x1; deltay=y2-y1; k=deltay/deltax; e=k-0.5; x=x1; y=y1; for (;x<=x2;x++){ putpixel(x,y,pixelcolor); if (e<0) e=e+k; else{ y=y-1; e=e+k-1; } }
2.三次参数样条曲线
(前置科技:Hermite曲线)
结论
推理
三次曲线的代数形式是:
其x方向上的分量可表示为
三次样条参数曲线
3.B样条曲线
二次B样条曲线
三次B样条曲线
三次B样条曲线的矩阵形式如下:
端点特性
绘制技巧
可用角点重叠和角点共线的技巧。角点重叠指控制点重合,角点共线指控制点位于同一条直线。
要在某处使得曲线段与特征多边形相切:二重角点。
要在某处使得曲线形状出现尖点或通过某一个角点:三重角点。
在某处使得曲线出现拐点:三角点共线。
使得曲线形状中切入一段直线:四角点共线。
代码
//参数:6个控制点。 for (int i = 0; i < 3; i++) { //以P[i],P[i+1],P[i+2],P[i+3]为控制点推出系数 double ax = -(p[i].x - 3 * p[i + 1].x + 3 * p[i + 2].x - p[i + 3].x) / 6; double ay = -(p[i].y - 3 * p[i + 1].y + 3 * p[i + 2].y - p[i + 3].y) / 6; double bx = (p[i].x - 2 * p[i + 1].x + p[i + 2].x) / 2; double by = (p[i].y - 2 * p[i + 1].y + p[i + 2].y) / 2; double cx = -(p[i].x - p[i + 2].x) / 2; double cy = -(p[i].y - p[i + 2].y) / 2; double dx = (p[i].x + 4 * p[i + 1].x + p[i + 2].x) / 6; double dy = (p[i].y + 4 * p[i + 1].y + p[i + 2].y) / 6; //以abcd的系数,以t为参数,绘制该段曲线 for (double t = 0; t <= 1; t = t + 0.001) { int xt = ax * t * t * t + bx * t * t + cx * t + dx; int yt = ay * t * t * t + by * t * t + cy * t + dy; pDC->MoveTo(xt, yt); pDC->LineTo(xt, yt); } }