|
楼主 |
发表于 2011-7-31 13:33:36
|
显示全部楼层
第一章 实践部分
第二节 一个实心三角形
先不说别的,如果你想用9860 SDK把你的程序的图形界面写的很炫的话,有一样
东西是必须的——画一个实心(填充的)多边形。
看下图,好像做到这一点并不难
图上垂直的红线的意思是按一个方向(比如从左向右)一路用直线填充过去,多
边形就成为实心的了。
上图看上去好像很简单,只要把四条边的解析式求出来不就行了么?那我只能说
你漏了凹四边形。那可就不好玩了。所以,我们把四边形分解成三角形来绘制。
如图,两种四边形都可以分解为两个三角形
但是问题又来了——三角形也画不了啊,填充的时候还是没法计算填充线的位置
于是我们继续向下分割
如图,三角形总能分解成有一条边是水平的两个三角形。这样问题就迎刃而解啦
如图,水平边的两个端点约定为(x1,y1)与(x2,y2),两条非水平边的方程可设为
- 已知(x1,y1),(x2,y2),(x3,y3)
- 线段1:y = k1 * x + b1
- 线段2:y = k2 * x + b2
- 可以推出
- k1 = (y1 - y3)/(x1 - x3);
- k2 = (y2 - y3)/(x2 - x3);
- b1 = y1 - k1 * x1;
- b2 = y2 - k2 * x2;
复制代码
有人可能会问了,有一条边事垂直的怎么办?那样斜率算出来是±∞啊(在C里确实如此)。
很简单,垂直的话(x1=x3或x2=x3),那一部分就不绘制了,反正垂直了也那边的一部分也
就不存在了。
有人还问了,如果是一个钝角三角形怎么办?不好绘制吧?
看图:
看到红色部分的那个扫描的直线l1没有?画这条直线的时候让x在区间[x2,x3]内不就行了
l的两个端点分别为 (x,k1*x+b1),(x,k2*x+b2)
钝角在左边的也是如此。
好了不多说了,把代码贴上
- void draw_horizontal_triangle
- (float x1,float y1,float x2,float y2,float x3,float y3)
- {
- // (x1,y1)o------o(x2,y2)
- // \ /
- // \ /
- // \/
- // o(x3,y3)
- float k1,k2,b1,b2;
- int x,y,ty;
- if (y1 != y2) return;
- if (x1>x2){
- float t;
- t = x2;x2 = x1;x1 = t;
- }
- k1 = (y1 - y3)/(x1 - x3);
- k2 = (y2 - y3)/(x2 - x3);
- b1 = y1 - k1 * x1;
- b2 = y2 - k2 * x2;
- if (x1 < x3){
- int t = x3 > x2 ? x2 : x3;
- for (x = x1;x <= t;++x){
- y = k1 * x + b1;
- Bdisp_DrawLineVRAM(x,y1,x,y);
- }
- }else{
- for (x = x3;x <= x1;++x){
- y = k1 * x + b1;
- ty = k2 * x + b2;
- Bdisp_DrawLineVRAM(x,ty,x,y);
- }
- }
- if (x3 < x2){
- for (x = x3 > x1 ? x3 : x1;x <= x2;++x){
- y = k2 * x + b2;
- Bdisp_DrawLineVRAM(x,y2,x,y);
- }
- }else{
- for (x = x2;x <= x3;++x){
- y = k1 * x + b1;
- ty = k2 * x + b2;
- Bdisp_DrawLineVRAM(x,y,x,ty);
- }
- }
- }
复制代码
将Addin_main改为以下代码
- int AddIn_main(int isAppli, unsigned short OptionNum)
- {
- unsigned int key;
- Bdisp_AllClr_DDVRAM();
- draw_horizontal_triangle (24,12, 64,12, 32,32);
- GetKey(&key);
- Bdisp_AllClr_DDVRAM();
- draw_horizontal_triangle (24,12, 64,12, 0,32);
- GetKey(&key);
- Bdisp_AllClr_DDVRAM();
- draw_horizontal_triangle (24,12, 64,12, 100,32);
- while(1){
- GetKey(&key);
- }
- return 1;
- }
复制代码
测试效果
而最后的任意三角实心三角形就很好写了
- void swap (int *a,int *b){int t;t = *a;*a = *b;*b = t;}
- void draw_triangle (int x1,int y1,
- int x2,int y2,
- int x3,int y3)
- {
- if ((x1==x2 && x2==x3) || (y1==y2 && y2==y3)) return;
- if (y2 < y1){
- swap(&x1,&x2);swap(&y1,&y2);
- }
- if (y3 < y1){
- swap(&x3,&x1);swap(&y3,&y1);
- }
- if (y3 < y2){
- swap(&x3,&x2);swap(&y3,&y2);
- }
- if (y1==y2 || y2==y3)
- draw_horizontal_triangle (x1,y1,x2,y2,x3,y3);
- else{
- int new_x = x1 + (int)((float)(y2-y1)*(float)(x3-x1)/(float)(y3-y1));
- draw_horizontal_triangle (new_x,y2,x2,y2,x1,y1);
- draw_horizontal_triangle (x2,y2,new_x,y2,x3,y3);
- }
- }
复制代码
测试一下draw_triangle(32,32,127,0,63,63);
好了,纯图形的东西暂时告一段落,下一节我们来一点实际的——一个自定义
的菜单。 |
评分
-
查看全部评分
|