计算机图形学(五)线段的中点分割裁剪算法讲解与源代码

因为CSDN现在上传不上去资源,所以使用了百度云。

源码下载:点我下载

基本思想:

对于每条线段P1P2分为三种情况处理:
 (1) 若P1P2完全在窗口内,则显示该线段P1P2简称“取”之。
 (2) 若P1P2明显在窗口外,则丢弃该线段,简称“弃”之。
 (3) 若线段不满足“取”或“弃”
的条件,则在交点处把线段分为两段。其中一段完全在窗口外,可弃之。然后对另一段重复上述处理。
为快速判断,采用如下编码方法:每个区域赋予4位编码CtCbCrCl。

定义:


 

本算法与Cohen-Sutherland算法一样首先对线段端点进行编码,并把线段与窗口的关系分为三种情况:全在、完全不在和线段和窗口有交。
对前两种情况,进行一样的处理。对于第三种情况,用中点分割的方法求出线段与窗口的交点。

 

描述算法:

求线段与窗口的交点,A、B分别为距P0、P1最近的可见点,Pm为P0、P1中点。

AB之间的连线即为线段P0、P1的可见部分。

从P0出发找最近可见点A的方法先求出P0、 P1的中点Pm ,若P0、Pm不是显然不可见的,并且P0 、P1在窗口中有可见部分,则距P0最近的可见点一定落在 P0 Pm上,所以用P0 Pm代替P0 P1;否则取PmP1代替P0 P1  再对新的P0 P1求中点Pm。
重复上述过程,直到PmP1长度小于给定的控制常数为止,此时Pm收敛于交点。

从P1出发找最近可见点B采用上面类似方法。

下面给出设置编码:

 

 
  1. # define MAX 1000

  2. # define LEFT 1

  3. # define RIGHT 2

  4. # define BOTTOM 4

  5. # define TOP 8

 
  1. int XL;

  2. int XR;

  3. int YB;

  4. int YT;

 
  1. CClipingView::CClipingView()

  2. {

  3. Draw=false;

  4. XL=120;

  5. XR=800;

  6. YB=400;

  7. YT=100;

  8. }

 
  1. int CClipingView::EnCode(CPoint p)

  2. {

  3. int code=0;

  4. if(p.x<XL) code|=LEFT;

  5. if(p.x>XR) code|=RIGHT;

  6. if(p.y<YT) code|=TOP;

  7. if(p.y>YB) code|=BOTTOM;

  8. return code;

  9. }

核心代码:

 

 

 
  1. void CClipingView::OnMove()

  2. {

  3. CDC *pDC;

  4. pDC=GetDC();

  5. CString str;

  6. CBrush bru;

  7. bru.CreateSolidBrush(RGB(255,0,0));

  8. CBrush *oldbru=pDC->SelectObject(&bru);

  9. CPoint temp,p;

  10. bool Y=true;

  11. while(1)

  12. {

  13. Y=true;

  14. CPen pen1(0,3,RGB(255,255,0));

  15. CPen *oldpen=pDC->SelectObject(&pen1);

  16. pDC->MoveTo(p1);

  17. pDC->LineTo(p2);

  18. pDC->SelectObject(oldpen);

  19. pDC->SelectObject(&bru);

  20. Invalidate();

  21. //this->

  22. Sleep(700);

  23. if(EnCode(p1)==EnCode(p2)&&EnCode(p2)==0)

  24. {

  25. Sleep(700);

  26. Invalidate();

  27. return;

  28. }

  29. else if((EnCode(p1)&EnCode(p2))!=0)

  30. {

  31. Yn=false;

  32. Sleep(700);

  33. Invalidate();

  34. return;

  35. }

  36. else

  37. {

  38. int i=0;

  39. while(1)

  40. {

  41. if(p1.x-p2.x<=1&&p1.x-p2.x>=-1)

  42. {

  43. p2=p;

  44. p1=temp;

  45. Sleep(700);

  46. break;

  47. }

  48. if(EnCode(p1)==0)

  49. {

  50. ExChange(p1,p2);

  51. pDC->TextOut(50,500,"交换P1和P2! ");

  52. pDC->TextOut(p1.x,p1.y+8,"P1");

  53. pDC->TextOut(p2.x,p2.y+8,"P2");

  54. Sleep(700);

  55. }

  56. if(Y)

  57. temp=p2;

  58. p.x=(p1.x+p2.x)/2;

  59. p.y=(p1.y+p2.y)/2;

  60.  
  61. pDC->TextOut(50,500,"求出中点坐标P! ");

  62. pDC->TextOut(p.x,p.y+8,"P");

  63. pDC->Ellipse(p.x-4,p.y+4,p.x+4,p.y-4);

  64. Sleep(700);

  65. if((EnCode(p1)&EnCode(p))!=0)

  66. {

  67. CPen pen(0,4,RGB(255,255,255));

  68. CPen *oldpen=pDC->SelectObject(&pen);

  69. pDC->MoveTo(p1);

  70. pDC->LineTo(p);

  71. pDC->SelectObject(oldpen);

  72. pDC->SelectObject(&bru);

  73. Sleep(700);

  74. p1=p;

  75. pDC->TextOut(50,500,"P1赋值为P! ");

  76. pDC->TextOut(p1.x,p1.y+8,"P1");

  77. pDC->Ellipse(p1.x-4,p1.y+4,p1.x+4,p1.y-4);

  78. Sleep(700);

  79. }

  80. else

  81. {

  82. CPen pen(0,4,RGB(255,255,255));

  83. CPen *oldpen=pDC->SelectObject(&pen);

  84. pDC->MoveTo(p2);

  85. pDC->LineTo(p);

  86. pDC->SelectObject(oldpen);

  87. pDC->SelectObject(&bru);

  88. Sleep(700);

  89. p2=p;

  90. pDC->TextOut(50,500,"P2赋值为P! ");

  91. pDC->TextOut(p2.x,p2.y+8,"P2");

  92. pDC->Ellipse(p2.x-4,p2.y+4,p2.x+4,p2.y-4);

  93. Sleep(700);

  94. }

  95. Y=false;

  96. }

  97. }

  98. }

  99. }

 
  1. void CClipingView::ExChange(CPoint &p1, CPoint &p2)

  2. {

  3. p1.x=p1.x^p2.x;

  4. p2.x=p1.x^p2.x;

  5. p1.x=p1.x^p2.x;

  6. p1.y=p1.y^p2.y;

  7. p2.y=p1.y^p2.y;

  8. p1.y=p1.y^p2.y;

  9. }


代码中我输出了一些算法运算时的过程在界面上。

 

说一下源码使用的过程:

1.一开始进来就是直线分割,可已选择在正常情况下,也可以选择在网格情况下。如果在网格情况下,请先设置网格大小。

2.可以点击“Draw”来画一个窗口。

3.画一条直线。

4.点击第一个“开”来运非网格下的直线分割。点击第3个开运行网格下的直线分割算法。

如果有什么问题,还望大家多多指教。一起学习,一起进步。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值