裁剪算法—— 中点分割裁剪算法
实验环境:VC6.0
算法思想:
中点分割算法与cohen sutherland算法一样,首先对线段端点进行编码,并把线段与窗口关系分为三种情况:全在窗口内、完全不在窗口内和线段与窗口有交。对前两种情况作一样处理。对第三种情况,用中点分割的方法求出线段与窗口的交点,即从P0点出发找出距P0点最近的可见点B,两个可见点之间的连线即为线段P0P1的可见部分。
采用中点分割算法从P0出发找最近可见点:先求出P0P1的中点Pm,若P0Pm不是显然不可见的,并且P0P1在窗口中有可见部分,则距P0最近的可见点一定落在P0Pm上,所以用P0Pm代替P0P1,否则取PmP1代替P0P1;再对新的P0P1求中点Pm。重复上述过程,直到PmP1长度小于给定的控制常数为止,此时Pm收敛于交点。
程序实现:
#include "stdafx.h" #include<stdio.h> #include<conio.h> #include<graphics.h> #include<math.h> #define LEFT 1 #define RIGHT 2 #define BOTTOM 4 #define TOP 8 void midpointLine(int x0,int y0,int x1,int y1,int color)//中点画线算法 { int a,b,d1,d2,d,x,y; a=y0-y1; b=x1-x0; d=2*a+b; d1=2*a; d2=2*(a+b); x=x0; y=y0; putpixel(x,y,color); while(x<x1) { if(d<0) { x++; y++; d+=d2; } else { x++; d+=d1; } putpixel(x,y,color); } } int encode(int x,int y,int XL,int XR,int YB,int YT)//编码 { int c=0; if(x<XL) c|=LEFT; if(x>XR) c|=RIGHT; if(y<YB) c|=BOTTOM; if(y>YT) c|=TOP; return c; } void MidLineClip(int x1,int y1,int x2,int y2,int XL,int XR,int YB,int YT) { int code1,code2,code3;// float x,y,d; int x3,x4=x2,y3,y4=y2; code1=encode(x1,y1,XL,XR,YB,YT); code2=encode(x2,y2,XL,XR,YB,YT); if((code1 & code2) != 0) { midpointLine(x1,y1,x2,y2,RGB(0,0,255));//如果直线在裁剪窗口外就用蓝色画出 printf("线段在窗口外!"); return; } while(1)//在线段与窗口有交的情况中,求出离P0最近的可见点 { x=(x1+x2)/2.0; y=(y1+y2)/2.0; d=sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1)); if(d<=1)//精度为1个像素 { x1=x; y1=y;break; } code3=encode(x,y,XL,XR,YB,YT); if((code1 & code3) != 0) { x1=x; y1=y; code1=encode(x1,y1,XL,XR,YB,YT); } else { x2=x; y2=y; } } x3=x1;y3=y1;//保存求出的交点坐标 x2=x4;y2=y4;//恢复P1的初值 while(1) //在线段与窗口有交的情况中,求出离P1最近的可见点 { x=(x1+x2)/2.0; y=(y1+y2)/2.0; d=sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2)); if(d<=1) { x2=x; y2=y;break; } code3=encode(x,y,XL,XR,YB,YT); if((code2 & code3) != 0) { x2=x; y2=y; code2=encode(x2,y2,XL,XR,YB,YT); } else { x1=x; y1=y; } } x1=x3;y1=y3; midpointLine(x1,y1,x2,y2,RGB(255,0,0));//将裁减的直线用红色标注 return; } int main(int argc, char* argv[]) { int gdriver=DETECT,gmode; int x1=20,y1=30,x2=250,y2=300,XL=10,XR=200,YT=400,YB=30; initgraph(&gdriver,&gmode,"c:\\tc"); cleardevice(); midpointLine(x1,y1,x2,y2,RGB(0,255,0));//将被裁剪直线用绿色画出 rectangle(10,400,200,30);//rectangle(int left,int top,int right,int bottom);//裁剪窗口 MidLineClip(x1,y1,x2,y2,XL,XR,YB,YT); getch(); closegraph(); return 0; }
显示效果:

换一组参数后,出现偏差:


浙公网安备 33010602011771号