C# 实现线段的编码裁剪算法(vs2010)

  1 using System;
  2 
  3 using System.Collections.Generic;
  4 
  5 using System.ComponentModel;
  6 
  7 using System.Data;
  8 
  9 using System.Drawing;
 10 
 11 using System.Linq;
 12 
 13 using System.Text;
 14 
 15 using System.Windows.Forms;
 16 
 17  
 18 
 19 namespace cutLine
 20 
 21 {
 22 
 23     unsafe public partial class Form1 : Form
 24 
 25     {
 26 
 27         const int left = 1;
 28 
 29         const int right = 2;
 30 
 31         const int bottom = 4;
 32 
 33         const int top = 8;
 34 
 35         Point window1, window2;     //保存裁剪区矩形
 36 
 37         Point line1, line2;         //保存线段的两个端点坐标
 38 
 39         int start, x , y;           //标志点击次数,取值范围0,1,2
 40 
 41         Graphics g;                 //GDI 对象
 42 
 43  
 44 
 45         public Form1()
 46 
 47         {
 48 
 49             InitializeComponent();
 50 
 51             g = CreateGraphics();
 52 
 53             window1 = new Point(120, 120);//裁剪区左下角
 54 
 55             window2 = new Point(600, 420); //裁剪区右上角
 56 
 57             start = 0;
 58 
 59         }
 60 
 61  
 62 
 63         private void Form1_MouseClick(object sender, MouseEventArgs e)
 64 
 65         {
 66 
 67             int x = e.X, y = e.Y;    //记录鼠标点击位置:
 68 
 69             Pen p = new Pen(Brushes.Black, 1);
 70 
 71             switch (start)
 72 
 73             {
 74 
 75                 case 0:
 76 
 77                     {
 78 
 79                         g.Clear(Color.Silver);
 80 
 81                         Background();
 82 
 83                         start = 1;
 84 
 85                         line1 = new Point(e.X, e.Y);
 86 
 87                         g.DrawRectangle(Pens.Black, x - 2, y - 2, 2, 2); //画一个小方块,显示点击位置
 88 
 89                         break;
 90 
 91                     }
 92 
 93                 case 1:
 94 
 95                     {
 96 
 97                         start = 0;
 98 
 99                         line2 = new Point(e.X, e.Y);
100 
101                         g.DrawRectangle(Pens.Black, x - 2, y - 2, 2, 2); //画一个小方块,显示点击位置
102 
103                         g.DrawLine(p, line1, line2);
104 
105                         //DrawString_1();
106 
107                         cutLine(line1, line2, window1.X, window2.X, window1.Y, window2.Y);
108 
109                         break;
110 
111                     }
112 
113             }
114 
115         }
116 
117  
118 
119         private void Background()
120 
121         {
122 
123             if (start == 0)
124 
125                 g.DrawRectangle(Pens.Black, window1.X, window1.Y,window2.X - window1.X, window2.Y - window1.Y);
126 
127             DrawString();
128 
129         }
130 
131  
132 
133         private void DrawString()
134 
135         {
136 
137             String str;
138 
139             str = "                              黑色矩形为裁剪窗口\n                              点鼠标输入线段的两个点,自动执行裁剪\n                              红色为线段裁剪后的部分";     //临时字体对象              //画刷枚举     //位置
140 
141             g.DrawString(str, new Font("宋体", 16, FontStyle.Regular), Brushes.Black, 20, 20);
142 
143         }
144 
145  
146 
147         private void DrawString_1(int code1, int code2)
148 
149         {
150 
151             String str;
152 
153             g.FillRectangle (Brushes.White, 120, 40, 190, 30);
154 
155             str = "\n编码: "   Convert.ToString(code1, 2).PadLeft(4, ’’0’’)   "  "   Convert.ToString(code2, 2).PadLeft(4, ’’0’’);
156 
157             g.DrawString(str, new Font("宋体", 16, FontStyle.Regular), Brushes.Black, 120, 20);
158 
159         }
160 
161  
162 
163         private void Form1_Load(object sender, EventArgs e)
164 
165         {  
166 
167         }
168 
169  
170 
171         private void Form1_Paint(object sender, PaintEventArgs e)
172 
173         {
174 
175             Background();
176 
177         }
178 
179        private void Encode(int x, int y,int *code,int xl, int xr, int yb, int yt)
180 
181         {
182 
183             int c = 0;
184 
185             if (x < xl)
186 
187                 c = c | left;
188 
189             else if (x > xr)
190 
191                 c = c | right;
192 
193             if (y < yb)
194 
195                 c = c | bottom;
196 
197             else if (y > yt)
198 
199                 c = c | top;
200 
201             (*code) = c;
202 
203         }
204 
205         public void cutLine(Point p1, Point p2, int xl, int xr, int yb, int yt)
206 
207         {
208 
209             Pen p = new Pen(Brushes.Red, 2);
210 
211             int x1, x2, y1, y2,code1, code2, code;
212 
213             x1 = p1.X; x2 = p2.X; y1 = p1.Y; y2 = p2.Y;
214 
215             Encode(x1,y1, &code1, xl,xr,yb,yt);
216 
217             Encode(x2,y2, &code2, xl,xr,yb,yt);
218 
219             DrawString_1(code1, code2);
220 
221             while (code1 != 0 || code2 != 0)
222 
223             {
224 
225                 if ((code1 & code2) != 0) return;
226 
227                 code = code1;
228 
229                 if (code1 == 0)
230 
231                     code = code2;
232 
233                 if ((left & code) != 0)//线段与左边界相交
234 
235                 {
236 
237                     x = xl;
238 
239                     y = y1   (y2 - y1) * (xl - x1) / (x2 - x1);
240 
241                 }
242 
243                 else if ((right & code) != 0)//线段与右边界相交
244 
245                 {
246 
247                     x = xr;
248 
249                     y = y1   (y2 - y1) * (xr - x1) / (x2 - x1);
250 
251                 }
252 
253                 else if ((bottom & code) != 0)//线段与下边界相交
254 
255                 {
256 
257                     y = yb;
258 
259                     x = x1   (x2 - x1) * (yb - y1) / (y2 - y1);
260 
261                 }
262 
263                 else if ((top & code) != 0)//线段与上边界相交
264 
265                 {
266 
267                     y = yt;
268 
269                     x = x1   (x2 - x1) * (yt - y1) / (y2 - y1);
270 
271                 }
272 
273                 if (code == code1)
274 
275                 {
276 
277                     x1 = x;
278 
279                     y1 = y;
280 
281                     Encode(x, y, &code1, xl, xr, yb, yt);
282 
283                 }
284 
285                 else
286 
287                 {
288 
289                     x2 = x;
290 
291                     y2 = y;
292 
293                     Encode(x, y, &code2, xl, xr, yb, yt);
294 
295                 }
296 
297             }
298 
299             p1.X = x1; p1.Y = y1;
300 
301             p2.X = x2; p2.Y = y2;
302 
303             g.DrawLine(p, p1, p2);
304 
305         }
306 
307     }
308 
309 }

 

posted @ 2014-05-16 23:21  青山应回首  阅读(804)  评论(0编辑  收藏  举报