Mercurial > traipse_dev
comparison orpg/mapper/region.py @ 20:072ffc1d466f traipse_dev
2nd attempt. Still untested.
author | sirebral |
---|---|
date | Sat, 25 Jul 2009 19:23:25 -0500 |
parents | 4385a7d0efd1 |
children | 449a8900f9ac |
comparison
equal
deleted
inserted
replaced
19:78407d627cba | 20:072ffc1d466f |
---|---|
40 self.endy=end.Y | 40 self.endy=end.Y |
41 self.dy=self.endy-self.starty | 41 self.dy=self.endy-self.starty |
42 self.cx=self.startx | 42 self.cx=self.startx |
43 self.bottom=0 | 43 self.bottom=0 |
44 self.dir = 0 | 44 self.dir = 0 |
45 if self.endx>self.startx: | 45 if self.endx>self.startx: self.dx = int((self.endx-self.startx)/self.dy) |
46 self.dx = int((self.endx-self.startx)/self.dy) | 46 else: self.dx = -int((self.startx-self.endx)/self.dy) |
47 else: | |
48 self.dx = -int((self.startx-self.endx)/self.dy) | |
49 self.error = 0 | 47 self.error = 0 |
50 if self.endx >= self.startx: | 48 if self.endx >= self.startx: self.inc = (self.endx-self.startx)%self.dy |
51 self.inc = (self.endx-self.startx)%self.dy | 49 else: self.inc = (self.startx-self.endx)%self.dy |
52 else: | |
53 self.inc = (self.startx-self.endx)%self.dy | |
54 | 50 |
55 def advance(self): | 51 def advance(self): |
56 self.cx += self.dx | 52 self.cx += self.dx |
57 self.error += self.inc | 53 self.error += self.inc |
58 if (self.error>=self.dy): | 54 if (self.error>=self.dy): |
59 if (self.endx<self.startx): | 55 if (self.endx<self.startx): self.cx -= 1 |
60 self.cx -= 1 | 56 else: self.cx += 1 |
61 else: | |
62 self.cx += 1 | |
63 self.error -= self.dy | 57 self.error -= self.dy |
64 | 58 |
65 # Utilitarian class for describing a coordinate in 2D space | 59 # Utilitarian class for describing a coordinate in 2D space |
66 class IPoint: | 60 class IPoint: |
67 def __init__(self): | 61 def __init__(self): |
83 self.X=x | 77 self.X=x |
84 self.Y=y | 78 self.Y=y |
85 return self | 79 return self |
86 | 80 |
87 def equals(self,b): | 81 def equals(self,b): |
88 if self.X==b.X and self.Y==b.Y: | 82 if self.X==b.X and self.Y==b.Y: return 1 |
89 return 1 | |
90 return 0 | 83 return 0 |
91 | 84 |
92 def less(self,b): | 85 def less(self,b): |
93 if self.Y<b.Y or (self.Y==b.Y and self.X<b.X): | 86 if self.Y<b.Y or (self.Y==b.Y and self.X<b.X): return 1 |
94 return 1 | |
95 return 0 | 87 return 0 |
96 | 88 |
97 def greater(self,b): | 89 def greater(self,b): |
98 if self.Y>b.Y or (self.Y==b.Y and self.X>b.X): | 90 if self.Y>b.Y or (self.Y==b.Y and self.X>b.X): return 1 |
99 return 1 | |
100 return 0 | 91 return 0 |
101 | 92 |
102 # generic rectangle class | 93 # generic rectangle class |
103 class IRect: | 94 class IRect: |
104 def __init__(self): #initializes to an invalid rectangle | 95 def __init__(self): #initializes to an invalid rectangle |
153 self.top+=nT | 144 self.top+=nT |
154 self.right+=nR | 145 self.right+=nR |
155 sel.bottom+=nB | 146 sel.bottom+=nB |
156 | 147 |
157 def IsValid(self): | 148 def IsValid(self): |
158 if (self.left<=self.right and self.top<=self.bottom): | 149 if (self.left<=self.right and self.top<=self.bottom): return 1 |
159 return 1 | |
160 return 0 | 150 return 0 |
161 | 151 |
162 def add(self,pt): | 152 def add(self,pt): |
163 return IRect().make(self.left+pt.X,self.top+pt.Y,self.right+pt.X,self.bottom+pt.Y) | 153 return IRect().make(self.left+pt.X,self.top+pt.Y,self.right+pt.X,self.bottom+pt.Y) |
164 | 154 |
170 | 160 |
171 def union(self,rect): | 161 def union(self,rect): |
172 return IRect().make(min(self.left,rect.left),min(self.top,rect.top),max(self.right,rect.right),max(self.bottom,rect.bottom)) | 162 return IRect().make(min(self.left,rect.left),min(self.top,rect.top),max(self.right,rect.right),max(self.bottom,rect.bottom)) |
173 | 163 |
174 def equals(self,rect): | 164 def equals(self,rect): |
175 if (self.top==rect.top and self.bottom==rect.bottom and self.left==rect.left and self.right==rect.right): | 165 if (self.top==rect.top and self.bottom==rect.bottom and self.left==rect.left and self.right==rect.right): return 1 |
176 return 1 | |
177 return 0 | 166 return 0 |
178 | 167 |
179 def make(self,l,t,r,b): | 168 def make(self,l,t,r,b): |
180 self.left=l | 169 self.left=l |
181 self.right=r | 170 self.right=r |
211 self.last=None | 200 self.last=None |
212 self.count=0 | 201 self.count=0 |
213 | 202 |
214 def __str__(self): | 203 def __str__(self): |
215 x="[" | 204 x="[" |
216 for y in self.GetList(): | 205 for y in self.GetList(): x+=" "+str(y.bounds)+" " |
217 x+=" "+str(y.bounds)+" " | |
218 x+="]" | 206 x+="]" |
219 return x | 207 return x |
220 | 208 |
221 #remove all rectangles from list | 209 #remove all rectangles from list |
222 def Clear(self): | 210 def Clear(self): |
229 | 217 |
230 #add a new clipping rectangle to list | 218 #add a new clipping rectangle to list |
231 def AddRect(self,rect): | 219 def AddRect(self,rect): |
232 rect.prev=None | 220 rect.prev=None |
233 rect.next=self.first | 221 rect.next=self.first |
234 if not (self.first is None): | 222 if not (self.first is None): self.first.prev=rect |
235 self.first.prev=rect | |
236 self.first=rect | 223 self.first=rect |
237 if self.last is None: | 224 if self.last is None: self.last=rect |
238 self.last=rect | |
239 self.count += 1 | 225 self.count += 1 |
240 | 226 |
241 #removes the passed clipping rectangle from the list | 227 #removes the passed clipping rectangle from the list |
242 def RemoveRect(self,rect): | 228 def RemoveRect(self,rect): |
243 if not (rect.prev is None): | 229 if not (rect.prev is None): rect.prev.next=rect.next |
244 rect.prev.next=rect.next | 230 else: self.first=rect.next |
245 else: | 231 if not (rect.next is None): rect.next.prev=rect.prev |
246 self.first=rect.next | 232 else: self.last=rect.prev |
247 if not (rect.next is None): | |
248 rect.next.prev=rect.prev | |
249 else: | |
250 self.last=rect.prev | |
251 self.count -= 1 | 233 self.count -= 1 |
252 | 234 |
253 # find the clipping rectangle at the the beginning of the list, remove it, | 235 # find the clipping rectangle at the the beginning of the list, remove it, |
254 # and return it | 236 # and return it |
255 def RemoveHead(self): | 237 def RemoveHead(self): |
256 if self.count==0: | 238 if self.count==0: return None |
257 return None | |
258 rect=self.first | 239 rect=self.first |
259 self.first=rect.next | 240 self.first=rect.next |
260 if (self.first is None): | 241 if (self.first is None): self.last=None |
261 self.last=None | |
262 self.count -= 1 | 242 self.count -= 1 |
263 return rect | 243 return rect |
264 | 244 |
265 # stealrects -- appends the list of clipping rectangles in pclist to the current | 245 # stealrects -- appends the list of clipping rectangles in pclist to the current |
266 # list. removes the entries from pclist | 246 # list. removes the entries from pclist |
267 def StealRects(self,pclist): | 247 def StealRects(self,pclist): |
268 if pclist.first is None: | 248 if pclist.first is None: return |
269 return | |
270 if self.first is None: | 249 if self.first is None: |
271 self.first=pclist.first | 250 self.first=pclist.first |
272 self.last=pclist.last | 251 self.last=pclist.last |
273 else: | 252 else: |
274 self.last.next=pclist.first | 253 self.last.next=pclist.first |
290 | 269 |
291 # some utility procedures, defined outside the scope of any class to ensure | 270 # some utility procedures, defined outside the scope of any class to ensure |
292 # efficiency | 271 # efficiency |
293 | 272 |
294 def _hSortCmp(rect1,rect2): | 273 def _hSortCmp(rect1,rect2): |
295 if (rect1.bounds.left<rect2.bounds.left): | 274 if (rect1.bounds.left<rect2.bounds.left): return -1 |
296 return -1 | 275 if (rect1.bounds.left>rect2.bounds.left): return 1 |
297 if (rect1.bounds.left>rect2.bounds.left): | 276 if (rect1.bounds.top<rect2.bounds.top): return -1 |
298 return 1 | 277 if (rect1.bounds.top>rect2.bounds.top): return 1 |
299 if (rect1.bounds.top<rect2.bounds.top): | |
300 return -1 | |
301 if (rect1.bounds.top>rect2.bounds.top): | |
302 return 1 | |
303 return 0 | 278 return 0 |
304 | 279 |
305 def _vSortCmp(rect1,rect2): | 280 def _vSortCmp(rect1,rect2): |
306 if (rect1.bounds.top<rect2.bounds.top): | 281 if (rect1.bounds.top<rect2.bounds.top): return -1 |
307 return -1 | 282 if (rect1.bounds.top>rect2.bounds.top): return 1 |
308 if (rect1.bounds.top>rect2.bounds.top): | 283 if (rect1.bounds.left<rect2.bounds.left): return -1 |
309 return 1 | 284 if (rect1.bounds.left>rect2.bounds.left): return 1 |
310 if (rect1.bounds.left<rect2.bounds.left): | |
311 return -1 | |
312 if (rect1.bounds.left>rect2.bounds.left): | |
313 return 1 | |
314 return 0 | 285 return 0 |
315 | 286 |
316 # this is the class for which this whole source file is designed! | 287 # this is the class for which this whole source file is designed! |
317 # a Region is maintained as an optimal set of non-intersecting rectangles | 288 # a Region is maintained as an optimal set of non-intersecting rectangles |
318 # whose union is the 2D area of interest. At the end of each of the public | 289 # whose union is the 2D area of interest. At the end of each of the public |
333 | 304 |
334 def Clear(self): | 305 def Clear(self): |
335 self.crects.Clear() | 306 self.crects.Clear() |
336 | 307 |
337 def isEmpty(self): | 308 def isEmpty(self): |
338 if self.crects.first: | 309 if self.crects.first: return 0 |
339 return 0 | |
340 return 1 | 310 return 1 |
341 | 311 |
342 def Copy(self,dest): | 312 def Copy(self,dest): |
343 dest.Clear() | 313 dest.Clear() |
344 p=self.crects.first | 314 p=self.crects.first |
381 for i in cnew: | 351 for i in cnew: |
382 if (i.IsValid()): | 352 if (i.IsValid()): |
383 newclip=self.__AllocClipRect() | 353 newclip=self.__AllocClipRect() |
384 newclip.bounds=i | 354 newclip.bounds=i |
385 newlist.AddRect(newclip) | 355 newlist.AddRect(newclip) |
386 else: | 356 else: newlist.AddRect(p) |
387 newlist.AddRect(p) | |
388 self.crects.StealRects(newlist) | 357 self.crects.StealRects(newlist) |
389 | 358 |
390 def __IncludeRect(self,rect): | 359 def __IncludeRect(self,rect): |
391 tmprg=IRegion() | 360 tmprg=IRegion() |
392 tmprg.__AddRect(rect) | 361 tmprg.__AddRect(rect) |
428 def __ExcludeRect(self,rect): | 397 def __ExcludeRect(self,rect): |
429 newlist=ClipRectList() | 398 newlist=ClipRectList() |
430 while not (self.crects.first is None): | 399 while not (self.crects.first is None): |
431 pcclip=self.crects.RemoveHead() | 400 pcclip=self.crects.RemoveHead() |
432 hide=rect.intersect(pcclip.bounds) | 401 hide=rect.intersect(pcclip.bounds) |
433 if not hide.IsValid(): | 402 if not hide.IsValid(): newlist.AddRect(pcclip) |
434 newlist.AddRect(pcclip) | |
435 else: | 403 else: |
436 #make 4 new rectangles to replace the one taken out | 404 #make 4 new rectangles to replace the one taken out |
437 # | 405 # |
438 # AAAAAAAAAAAA | 406 # AAAAAAAAAAAA |
439 # AAAAAAAAAAAA | 407 # AAAAAAAAAAAA |
474 def __IntersectRect(self,rect): | 442 def __IntersectRect(self,rect): |
475 newlist=ClipRectList() | 443 newlist=ClipRectList() |
476 while not self.crects.first is None: | 444 while not self.crects.first is None: |
477 pcclip=self.crects.RemoveHead() | 445 pcclip=self.crects.RemoveHead() |
478 hide=rect.intersect(pcclip.bounds) | 446 hide=rect.intersect(pcclip.bounds) |
479 if not hide.IsValid(): | 447 if not hide.IsValid(): newlist.AddRect(pcclip) |
480 newlist.AddRect(pcclip) | |
481 else: | 448 else: |
482 cnew=[IRect().make(pcclip.bounds.left,hide.top,hide.left-1,hide.bottom), | 449 cnew=[IRect().make(pcclip.bounds.left,hide.top,hide.left-1,hide.bottom), |
483 IRect().make(hide.right+1,hide.top,pcclip.bounds.right,hide.bottom), | 450 IRect().make(hide.right+1,hide.top,pcclip.bounds.right,hide.bottom), |
484 IRect().make(pcclip.bounds.left,hide.bottom+1,pcclip.bounds.right,pcclip.bounds.bottom), | 451 IRect().make(pcclip.bounds.left,hide.bottom+1,pcclip.bounds.right,pcclip.bounds.bottom), |
485 IRect().make(pcclip.bounds.left,pcclip.bounds.top,pcclip.bounds.right,hide.top-1) ] | 452 IRect().make(pcclip.bounds.left,pcclip.bounds.top,pcclip.bounds.right,hide.top-1) ] |
538 x=clist[i+1] | 505 x=clist[i+1] |
539 del clist[i+1] | 506 del clist[i+1] |
540 self.crects.RemoveRect(x) | 507 self.crects.RemoveRect(x) |
541 self.__FreeClipRect(x) | 508 self.__FreeClipRect(x) |
542 keepgoing=1 | 509 keepgoing=1 |
543 if len(clist)<=1: | 510 if len(clist)<=1: break |
544 break | |
545 clist.sort(lambda a,b:_hSortCmp(a,b)) | 511 clist.sort(lambda a,b:_hSortCmp(a,b)) |
546 keys=range(len(clist)-1) | 512 keys=range(len(clist)-1) |
547 keys.reverse() | 513 keys.reverse() |
548 for i in keys: | 514 for i in keys: |
549 if (clist[i].bounds.bottom==clist[i+1].bounds.top-1 and | 515 if (clist[i].bounds.bottom==clist[i+1].bounds.top-1 and |
561 for i in thelist: | 527 for i in thelist: |
562 r=IRect().make(i.left,i.y,i.right,i.y) | 528 r=IRect().make(i.left,i.y,i.right,i.y) |
563 if mode: | 529 if mode: |
564 self.__Examine(r) | 530 self.__Examine(r) |
565 self.__IncludeRect(r) | 531 self.__IncludeRect(r) |
566 else: | 532 else: self.__ExcludeRect(r) |
567 self.__ExcludeRect(r) | |
568 self.Optimize() | 533 self.Optimize() |
569 | 534 |
570 def GetRectList(self): | 535 def GetRectList(self): |
571 result=[] | 536 result=[] |
572 i = self.crects.first | 537 i = self.crects.first |
603 sx = min(polypt[i].X,polypt[n].X) | 568 sx = min(polypt[i].X,polypt[n].X) |
604 ex = max(polypt[i].X,polypt[n].X) | 569 ex = max(polypt[i].X,polypt[n].X) |
605 result.append(ISpan(sx,ex,polypt[i].Y)) | 570 result.append(ISpan(sx,ex,polypt[i].Y)) |
606 size = len(polylines) | 571 size = len(polylines) |
607 for i in xrange(size): | 572 for i in xrange(size): |
608 if i == 0 and polylines[i].dir == -1: | 573 if i == 0 and polylines[i].dir == -1: n = size-1 |
609 n = size-1 | 574 elif (polylines[i].dir == -1): n = i-1 |
610 elif (polylines[i].dir == -1): | 575 else: n = (i+1) % size |
611 n = i-1 | 576 if (polylines[i].dir != polylines[n].dir): polylines[i].bottom = 1 |
612 else: | 577 if i == 0 or polylines[i].starty < y: y = polylines[i].starty |
613 n = (i+1) % size | 578 if not ET.has_key(polylines[i].starty): ET[polylines[i].starty] = [] |
614 if (polylines[i].dir != polylines[n].dir): #find out if at bottom end | |
615 polylines[i].bottom = 1 | |
616 if i == 0 or polylines[i].starty < y: | |
617 y = polylines[i].starty | |
618 if not ET.has_key(polylines[i].starty): | |
619 ET[polylines[i].starty] = [] | |
620 ET[polylines[i].starty].append(polylines[i]) #add to edge table, indexed by smaller y coordinate | 579 ET[polylines[i].starty].append(polylines[i]) #add to edge table, indexed by smaller y coordinate |
621 AET = [] #active edge table | 580 AET = [] #active edge table |
622 while len(AET) > 0 or len(ET) > 0: | 581 while len(AET) > 0 or len(ET) > 0: |
623 if ET.has_key(y): #if current y value has entries in edge tabe | 582 if ET.has_key(y): #if current y value has entries in edge tabe |
624 AET.extend(ET[y]) # add them to active edge table | 583 AET.extend(ET[y]) # add them to active edge table |