Freestyle: remove a bunch of debug prints in the python code, these are confusing
[blender.git] / release / scripts / freestyle / style_modules / ChainingIterators.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 #  Filename : ChainingIterators.py
20 #  Author   : Stephane Grabli
21 #  Date     : 04/08/2005
22 #  Purpose  : Chaining Iterators to be used with chaining operators
23
24 from freestyle import AdjacencyIterator, ChainingIterator, ExternalContourUP1D, Nature, TVertex
25 from freestyle import ContextFunctions as CF
26
27 import bpy
28
29 ## the natural chaining iterator
30 ## It follows the edges of same nature following the topology of
31 ## objects with  preseance on silhouettes, then borders, 
32 ## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice
33 ## You can specify whether to stay in the selection or not.
34 class pyChainSilhouetteIterator(ChainingIterator):
35         def __init__(self, stayInSelection=True):
36                 ChainingIterator.__init__(self, stayInSelection, True, None, True)
37         def init(self):
38                 pass
39         def traverse(self, iter):
40                 winner = None
41                 it = AdjacencyIterator(iter)
42                 tvertex = self.next_vertex
43                 if type(tvertex) is TVertex:
44                         mateVE = tvertex.get_mate(self.current_edge)
45                         while not it.is_end:
46                                 ve = it.object
47                                 if ve.id == mateVE.id:
48                                         winner = ve
49                                         break
50                                 it.increment()
51                 else:
52                         ## case of NonTVertex
53                         natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
54                         for i in range(len(natures)):
55                                 currentNature = self.current_edge.nature
56                                 if (natures[i] & currentNature) != 0:
57                                         count=0
58                                         while not it.is_end:
59                                                 visitNext = 0
60                                                 oNature = it.object.nature
61                                                 if (oNature & natures[i]) != 0:
62                                                         if natures[i] != oNature:
63                                                                 for j in range(i):
64                                                                         if (natures[j] & oNature) != 0:
65                                                                                 visitNext = 1
66                                                                                 break
67                                                                 if visitNext != 0:
68                                                                         break    
69                                                         count = count+1
70                                                         winner = it.object
71                                                 it.increment()
72                                         if count != 1:
73                                                 winner = None
74                                         break
75                 return winner
76
77 ## the natural chaining iterator
78 ## It follows the edges of same nature on the same
79 ## objects with  preseance on silhouettes, then borders, 
80 ## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice
81 ## You can specify whether to stay in the selection or not.
82 ## You can specify whether to chain iterate over edges that were 
83 ## already visited or not.
84 class pyChainSilhouetteGenericIterator(ChainingIterator):
85         def __init__(self, stayInSelection=True, stayInUnvisited=True):
86                 ChainingIterator.__init__(self, stayInSelection, stayInUnvisited, None, True)
87         def init(self):
88                 pass
89         def traverse(self, iter):
90                 winner = None
91                 it = AdjacencyIterator(iter)
92                 tvertex = self.next_vertex
93                 if type(tvertex) is TVertex:
94                         mateVE = tvertex.get_mate(self.current_edge)
95                         while not it.is_end:
96                                 ve = it.object
97                                 if ve.id == mateVE.id:
98                                         winner = ve
99                                         break
100                                 it.increment()
101                 else:
102                         ## case of NonTVertex
103                         natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
104                         for i in range(len(natures)):
105                                 currentNature = self.current_edge.nature
106                                 if (natures[i] & currentNature) != 0:
107                                         count=0
108                                         while not it.is_end:
109                                                 visitNext = 0
110                                                 oNature = it.object.nature
111                                                 ve = it.object
112                                                 if ve.id == self.current_edge.id:
113                                                         it.increment()
114                                                         continue
115                                                 if (oNature & natures[i]) != 0:
116                                                         if natures[i] != oNature:
117                                                                 for j in range(i):
118                                                                         if (natures[j] & oNature) != 0:
119                                                                                 visitNext = 1
120                                                                                 break
121                                                                 if visitNext != 0:
122                                                                         break    
123                                                         count = count+1
124                                                         winner = ve
125                                                 it.increment()
126                                         if count != 1:
127                                                 winner = None
128                                         break
129                 return winner
130                         
131 class pyExternalContourChainingIterator(ChainingIterator):
132         def __init__(self):
133                 ChainingIterator.__init__(self, False, True, None, True)
134                 self._isExternalContour = ExternalContourUP1D()
135         def init(self):
136                 self._nEdges = 0
137                 self._isInSelection = 1
138         def checkViewEdge(self, ve, orientation):
139                 if orientation != 0:
140                         vertex = ve.second_svertex()
141                 else:
142                         vertex = ve.first_svertex()
143                 it = AdjacencyIterator(vertex,1,1)
144                 while not it.is_end:
145                         ave = it.object
146                         if self._isExternalContour(ave):
147                                 return 1
148                         it.increment()
149                 print("pyExternlContourChainingIterator : didn't find next edge")
150                 return 0
151         def traverse(self, iter):
152                 winner = None
153                 it = AdjacencyIterator(iter)
154                 while not it.is_end:
155                         ve = it.object
156                         if self._isExternalContour(ve):
157                                 if ve.time_stamp == CF.get_time_stamp():
158                                         winner = ve
159                         it.increment()
160                 
161                 self._nEdges = self._nEdges+1
162                 if winner is None:
163                         orient = 1
164                         it = AdjacencyIterator(iter)
165                         while not it.is_end:
166                                 ve = it.object
167                                 if it.is_incoming:
168                                         orient = 0
169                                 good = self.checkViewEdge(ve,orient)
170                                 if good != 0:
171                                         winner = ve
172                                 it.increment()
173                 return winner
174
175 ## the natural chaining iterator
176 ## with a sketchy multiple touch
177 class pySketchyChainSilhouetteIterator(ChainingIterator):
178         def __init__(self, nRounds=3,stayInSelection=True):
179                 ChainingIterator.__init__(self, stayInSelection, False, None, True)
180                 self._timeStamp = CF.get_time_stamp()+nRounds
181                 self._nRounds = nRounds
182         def init(self):
183                 self._timeStamp = CF.get_time_stamp()+self._nRounds
184         def traverse(self, iter):
185                 winner = None
186                 it = AdjacencyIterator(iter)
187                 tvertex = self.next_vertex
188                 if type(tvertex) is TVertex:
189                         mateVE = tvertex.get_mate(self.current_edge)
190                         while not it.is_end:
191                                 ve = it.object
192                                 if ve.id == mateVE.id:
193                                         winner = ve
194                                         break
195                                 it.increment()
196                 else:
197                         ## case of NonTVertex
198                         natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
199                         for i in range(len(natures)):
200                                 currentNature = self.current_edge.nature
201                                 if (natures[i] & currentNature) != 0:
202                                         count=0
203                                         while not it.is_end:
204                                                 visitNext = 0
205                                                 oNature = it.object.nature
206                                                 ve = it.object
207                                                 if ve.id == self.current_edge.id:
208                                                         it.increment()
209                                                         continue
210                                                 if (oNature & natures[i]) != 0:
211                                                         if (natures[i] != oNature) != 0:
212                                                                 for j in range(i):
213                                                                         if (natures[j] & oNature) != 0:
214                                                                                 visitNext = 1
215                                                                                 break
216                                                                 if visitNext != 0:
217                                                                         break
218                                                         count = count+1
219                                                         winner = ve
220                                                 it.increment()
221                                         if count != 1:
222                                                 winner = None
223                                         break
224                 if winner is None:
225                         winner = self.current_edge
226                 if winner.chaining_time_stamp == self._timeStamp:
227                         winner = None
228                 return winner
229
230
231 # Chaining iterator designed for sketchy style.
232 # can chain several times the same ViewEdge
233 # in order to produce multiple strokes per ViewEdge.
234 class pySketchyChainingIterator(ChainingIterator):
235         def __init__(self, nRounds=3, stayInSelection=True):
236                 ChainingIterator.__init__(self, stayInSelection, False, None, True)
237                 self._timeStamp = CF.get_time_stamp()+nRounds
238                 self._nRounds = nRounds
239         def init(self):
240                 self._timeStamp = CF.get_time_stamp()+self._nRounds
241         def traverse(self, iter):
242                 winner = None
243                 found = False
244                 it = AdjacencyIterator(iter)
245                 while not it.is_end:
246                         ve = it.object
247                         if ve.id == self.current_edge.id:
248                                 found = True
249                                 it.increment()
250                                 continue
251                         winner = ve
252                         it.increment()
253                 if not found:
254                         # This is a fatal error condition: self.current_edge must be found
255                         # among the edges seen by the AdjacencyIterator [bug #35695].
256                         if bpy.app.debug_freestyle:
257                                 print('pySketchyChainingIterator: current edge not found')
258                         return None
259                 if winner is None:
260                         winner = self.current_edge
261                 if winner.chaining_time_stamp == self._timeStamp:
262                         return None
263                 return winner
264
265
266 ## Chaining iterator that fills small occlusions
267 ##      percent
268 ##              The max length of the occluded part 
269 ##              expressed in % of the total chain length
270 class pyFillOcclusionsRelativeChainingIterator(ChainingIterator):
271         def __init__(self, percent):
272                 ChainingIterator.__init__(self, False, True, None, True)
273                 self._length = 0
274                 self._percent = float(percent)
275         def init(self):
276                 # each time we're evaluating a chain length 
277                 # we try to do it once. Thus we reinit 
278                 # the chain length here:
279                 self._length = 0
280         def traverse(self, iter):
281                 winner = None
282                 winnerOrientation = 0
283                 #print(self.current_edge.id.first, self.current_edge.id.second)
284                 it = AdjacencyIterator(iter)
285                 tvertex = self.next_vertex
286                 if type(tvertex) is TVertex:
287                         mateVE = tvertex.get_mate(self.current_edge)
288                         while not it.is_end:
289                                 ve = it.object
290                                 if ve.id == mateVE.id:
291                                         winner = ve
292                                         if not it.is_incoming:
293                                                 winnerOrientation = 1
294                                         else:
295                                                 winnerOrientation = 0
296                                         break
297                                 it.increment()
298                 else:
299                         ## case of NonTVertex
300                         natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
301                         for nat in natures:
302                                 if (self.current_edge.nature & nat) != 0:
303                                         count=0
304                                         while not it.is_end:
305                                                 ve = it.object
306                                                 if (ve.nature & nat) != 0:
307                                                         count = count+1
308                                                         winner = ve
309                                                         if not it.is_incoming:
310                                                                 winnerOrientation = 1
311                                                         else:
312                                                                 winnerOrientation = 0
313                                                 it.increment()
314                                         if count != 1:
315                                                 winner = None
316                                         break
317                 if winner is not None:
318                         # check whether this edge was part of the selection
319                         if winner.time_stamp != CF.get_time_stamp():
320                                 #print("---", winner.id.first, winner.id.second)
321                                 # if not, let's check whether it's short enough with
322                                 # respect to the chain made without staying in the selection
323                                 #------------------------------------------------------------
324                                 # Did we compute the prospective chain length already ?
325                                 if self._length == 0:
326                                         #if not, let's do it
327                                         _it = pyChainSilhouetteGenericIterator(0,0)
328                                         _it.begin = winner
329                                         _it.current_edge = winner
330                                         _it.orientation = winnerOrientation
331                                         _it.init()
332                                         while not _it.is_end:
333                                                 ve = _it.object
334                                                 #print("--------", ve.id.first, ve.id.second)
335                                                 self._length = self._length + ve.length_2d
336                                                 _it.increment()
337                                                 if _it.is_begin:
338                                                         break;
339                                         _it.begin = winner
340                                         _it.current_edge = winner
341                                         _it.orientation = winnerOrientation
342                                         if not _it.is_begin:
343                                                 _it.decrement()
344                                                 while (not _it.is_end) and (not _it.is_begin):
345                                                         ve = _it.object
346                                                         #print("--------", ve.id.first, ve.id.second)
347                                                         self._length = self._length + ve.length_2d
348                                                         _it.decrement()
349
350                                 # let's do the comparison:
351                                 # nw let's compute the length of this connex non selected part:
352                                 connexl = 0
353                                 _cit = pyChainSilhouetteGenericIterator(0,0)
354                                 _cit.begin = winner
355                                 _cit.current_edge = winner
356                                 _cit.orientation = winnerOrientation
357                                 _cit.init()
358                                 while _cit.is_end == 0 and _cit.object.time_stamp != CF.get_time_stamp():
359                                         ve = _cit.object
360                                         #print("-------- --------", ve.id.first, ve.id.second)
361                                         connexl = connexl + ve.length_2d
362                                         _cit.increment()
363                                 if connexl > self._percent * self._length:
364                                         winner = None
365                 return winner
366
367 ## Chaining iterator that fills small occlusions
368 ##      size
369 ##              The max length of the occluded part 
370 ##              expressed in pixels
371 class pyFillOcclusionsAbsoluteChainingIterator(ChainingIterator):
372         def __init__(self, length):
373                 ChainingIterator.__init__(self, False, True, None, True)
374                 self._length = float(length)
375         def init(self):
376                 pass
377         def traverse(self, iter):
378                 winner = None
379                 winnerOrientation = 0
380                 #print(self.current_edge.id.first, self.current_edge.id.second)
381                 it = AdjacencyIterator(iter)
382                 tvertex = self.next_vertex
383                 if type(tvertex) is TVertex:
384                         mateVE = tvertex.get_mate(self.current_edge)
385                         while not it.is_end:
386                                 ve = it.object
387                                 if ve.id == mateVE.id:
388                                         winner = ve
389                                         if not it.is_incoming:
390                                                 winnerOrientation = 1
391                                         else:
392                                                 winnerOrientation = 0
393                                         break
394                                 it.increment()
395                 else:
396                         ## case of NonTVertex
397                         natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
398                         for nat in natures:
399                                 if (self.current_edge.nature & nat) != 0:
400                                         count=0
401                                         while not it.is_end:
402                                                 ve = it.object
403                                                 if (ve.nature & nat) != 0:
404                                                         count = count+1
405                                                         winner = ve
406                                                         if not it.is_incoming:
407                                                                 winnerOrientation = 1
408                                                         else:
409                                                                 winnerOrientation = 0
410                                                 it.increment()
411                                         if count != 1:
412                                                 winner = None
413                                         break
414                 if winner is not None:
415                         # check whether this edge was part of the selection
416                         if winner.time_stamp != CF.get_time_stamp():
417                                 #print("---", winner.id.first, winner.id.second)
418                                 # nw let's compute the length of this connex non selected part:
419                                 connexl = 0
420                                 _cit = pyChainSilhouetteGenericIterator(0,0)
421                                 _cit.begin = winner
422                                 _cit.current_edge = winner
423                                 _cit.orientation = winnerOrientation
424                                 _cit.init()
425                                 while _cit.is_end == 0 and _cit.object.time_stamp != CF.get_time_stamp():
426                                         ve = _cit.object
427                                         #print("-------- --------", ve.id.first, ve.id.second)
428                                         connexl = connexl + ve.length_2d
429                                         _cit.increment()
430                                 if connexl > self._length:
431                                         winner = None
432                 return winner
433
434
435 ## Chaining iterator that fills small occlusions
436 ##      percent
437 ##              The max length of the occluded part 
438 ##              expressed in % of the total chain length
439 class pyFillOcclusionsAbsoluteAndRelativeChainingIterator(ChainingIterator):
440         def __init__(self, percent, l):
441                 ChainingIterator.__init__(self, False, True, None, True)
442                 self._length = 0
443                 self._absLength = l
444                 self._percent = float(percent)
445         def init(self):
446                 # each time we're evaluating a chain length 
447                 # we try to do it once. Thus we reinit 
448                 # the chain length here:
449                 self._length = 0
450         def traverse(self, iter):
451                 winner = None
452                 winnerOrientation = 0
453                 #print(self.current_edge.id.first, self.current_edge.id.second)
454                 it = AdjacencyIterator(iter)
455                 tvertex = self.next_vertex
456                 if type(tvertex) is TVertex:
457                         mateVE = tvertex.get_mate(self.current_edge)
458                         while not it.is_end:
459                                 ve = it.object
460                                 if ve.id == mateVE.id:
461                                         winner = ve
462                                         if not it.is_incoming:
463                                                 winnerOrientation = 1
464                                         else:
465                                                 winnerOrientation = 0
466                                         break
467                                 it.increment()
468                 else:
469                         ## case of NonTVertex
470                         natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
471                         for nat in natures:
472                                 if (self.current_edge.nature & nat) != 0:
473                                         count=0
474                                         while not it.is_end:
475                                                 ve = it.object
476                                                 if (ve.nature & nat) != 0:
477                                                         count = count+1
478                                                         winner = ve
479                                                         if not it.is_incoming:
480                                                                 winnerOrientation = 1
481                                                         else:
482                                                                 winnerOrientation = 0
483                                                 it.increment()
484                                         if count != 1:
485                                                 winner = None
486                                         break
487                 if winner is not None:
488                         # check whether this edge was part of the selection
489                         if winner.time_stamp != CF.get_time_stamp():
490                                 #print("---", winner.id.first, winner.id.second)
491                                 # if not, let's check whether it's short enough with
492                                 # respect to the chain made without staying in the selection
493                                 #------------------------------------------------------------
494                                 # Did we compute the prospective chain length already ?
495                                 if self._length == 0:
496                                         #if not, let's do it
497                                         _it = pyChainSilhouetteGenericIterator(0,0)
498                                         _it.begin = winner
499                                         _it.current_edge = winner
500                                         _it.orientation = winnerOrientation
501                                         _it.init()
502                                         while not _it.is_end:
503                                                 ve = _it.object
504                                                 #print("--------", ve.id.first, ve.id.second)
505                                                 self._length = self._length + ve.length_2d
506                                                 _it.increment()
507                                                 if _it.is_begin:
508                                                         break;
509                                         _it.begin = winner
510                                         _it.current_edge = winner
511                                         _it.orientation = winnerOrientation
512                                         if not _it.is_begin:
513                                                 _it.decrement()
514                                                 while (not _it.is_end) and (not _it.is_begin):
515                                                         ve = _it.object
516                                                         #print("--------", ve.id.first, ve.id.second)
517                                                         self._length = self._length + ve.length_2d
518                                                         _it.decrement()
519
520                                 # let's do the comparison:
521                                 # nw let's compute the length of this connex non selected part:
522                                 connexl = 0
523                                 _cit = pyChainSilhouetteGenericIterator(0,0)
524                                 _cit.begin = winner
525                                 _cit.current_edge = winner
526                                 _cit.orientation = winnerOrientation
527                                 _cit.init()
528                                 while _cit.is_end == 0 and _cit.object.time_stamp != CF.get_time_stamp():
529                                         ve = _cit.object
530                                         #print("-------- --------", ve.id.first, ve.id.second)
531                                         connexl = connexl + ve.length_2d
532                                         _cit.increment()
533                                 if (connexl > self._percent * self._length) or (connexl > self._absLength):
534                                         winner = None
535                 return winner
536
537 ## Chaining iterator that fills small occlusions without caring about the 
538 ## actual selection
539 ##      percent
540 ##              The max length of the occluded part 
541 ##              expressed in % of the total chain length
542 class pyFillQi0AbsoluteAndRelativeChainingIterator(ChainingIterator):
543         def __init__(self, percent, l):
544                 ChainingIterator.__init__(self, False, True, None, True)
545                 self._length = 0
546                 self._absLength = l
547                 self._percent = float(percent)
548         def init(self):
549                 # each time we're evaluating a chain length 
550                 # we try to do it once. Thus we reinit 
551                 # the chain length here:
552                 self._length = 0
553         def traverse(self, iter):
554                 winner = None
555                 winnerOrientation = 0
556                 #print(self.current_edge.id.first, self.current_edge.id.second)
557                 it = AdjacencyIterator(iter)
558                 tvertex = self.next_vertex
559                 if type(tvertex) is TVertex:
560                         mateVE = tvertex.get_mate(self.current_edge)
561                         while not it.is_end:
562                                 ve = it.object
563                                 if ve.id == mateVE.id:
564                                         winner = ve
565                                         if not it.is_incoming:
566                                                 winnerOrientation = 1
567                                         else:
568                                                 winnerOrientation = 0
569                                         break
570                                 it.increment()
571                 else:
572                         ## case of NonTVertex
573                         natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
574                         for nat in natures:
575                                 if (self.current_edge.nature & nat) != 0:
576                                         count=0
577                                         while not it.is_end:
578                                                 ve = it.object
579                                                 if (ve.nature & nat) != 0:
580                                                         count = count+1
581                                                         winner = ve
582                                                         if not it.is_incoming:
583                                                                 winnerOrientation = 1
584                                                         else:
585                                                                 winnerOrientation = 0
586                                                 it.increment()
587                                         if count != 1:
588                                                 winner = None
589                                         break
590                 if winner is not None:
591                         # check whether this edge was part of the selection
592                         if winner.qi != 0:
593                                 #print("---", winner.id.first, winner.id.second)
594                                 # if not, let's check whether it's short enough with
595                                 # respect to the chain made without staying in the selection
596                                 #------------------------------------------------------------
597                                 # Did we compute the prospective chain length already ?
598                                 if self._length == 0:
599                                         #if not, let's do it
600                                         _it = pyChainSilhouetteGenericIterator(0,0)
601                                         _it.begin = winner
602                                         _it.current_edge = winner
603                                         _it.orientation = winnerOrientation
604                                         _it.init()
605                                         while not _it.is_end:
606                                                 ve = _it.object
607                                                 #print("--------", ve.id.first, ve.id.second)
608                                                 self._length = self._length + ve.length_2d
609                                                 _it.increment()
610                                                 if _it.is_begin:
611                                                         break;
612                                         _it.begin = winner
613                                         _it.current_edge = winner
614                                         _it.orientation = winnerOrientation
615                                         if not _it.is_begin:
616                                                 _it.decrement()
617                                                 while (not _it.is_end) and (not _it.is_begin):
618                                                         ve = _it.object
619                                                         #print("--------", ve.id.first, ve.id.second)
620                                                         self._length = self._length + ve.length_2d
621                                                         _it.decrement()
622
623                                 # let's do the comparison:
624                                 # nw let's compute the length of this connex non selected part:
625                                 connexl = 0
626                                 _cit = pyChainSilhouetteGenericIterator(0,0)
627                                 _cit.begin = winner
628                                 _cit.current_edge = winner
629                                 _cit.orientation = winnerOrientation
630                                 _cit.init()
631                                 while not _cit.is_end and _cit.object.qi != 0:
632                                         ve = _cit.object
633                                         #print("-------- --------", ve.id.first, ve.id.second)
634                                         connexl = connexl + ve.length_2d
635                                         _cit.increment()
636                                 if (connexl > self._percent * self._length) or (connexl > self._absLength):
637                                         winner = None
638                 return winner
639
640
641 ## the natural chaining iterator
642 ## It follows the edges of same nature on the same
643 ## objects with  preseance on silhouettes, then borders, 
644 ## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice
645 ## You can specify whether to stay in the selection or not.
646 class pyNoIdChainSilhouetteIterator(ChainingIterator):
647         def __init__(self, stayInSelection=True):
648                 ChainingIterator.__init__(self, stayInSelection, True, None, True)
649         def init(self):
650                 pass
651         def traverse(self, iter):
652                 winner = None
653                 it = AdjacencyIterator(iter)
654                 tvertex = self.next_vertex
655                 if type(tvertex) is TVertex:
656                         mateVE = tvertex.get_mate(self.current_edge)
657                         while not it.is_end:
658                                 ve = it.object
659                                 feB = self.current_edge.last_fedge
660                                 feA = ve.first_fedge
661                                 vB = feB.second_svertex
662                                 vA = feA.first_svertex
663                                 if vA.id.first == vB.id.first:
664                                         winner = ve
665                                         break
666                                 feA = self.current_edge.first_fedge
667                                 feB = ve.last_fedge
668                                 vB = feB.second_svertex
669                                 vA = feA.first_svertex
670                                 if vA.id.first == vB.id.first:
671                                         winner = ve
672                                         break
673                                 feA = self.current_edge.last_fedge
674                                 feB = ve.last_fedge
675                                 vB = feB.second_svertex
676                                 vA = feA.second_svertex
677                                 if vA.id.first == vB.id.first:
678                                         winner = ve
679                                         break
680                                 feA = self.current_edge.first_fedge
681                                 feB = ve.first_fedge
682                                 vB = feB.first_svertex
683                                 vA = feA.first_svertex
684                                 if vA.id.first == vB.id.first:
685                                         winner = ve
686                                         break
687                                 it.increment()
688                 else:
689                         ## case of NonTVertex
690                         natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
691                         for i in range(len(natures)):
692                                 currentNature = self.current_edge.nature
693                                 if (natures[i] & currentNature) != 0:
694                                         count=0
695                                         while not it.is_end:
696                                                 visitNext = 0
697                                                 oNature = it.object.nature
698                                                 if (oNature & natures[i]) != 0:
699                                                         if natures[i] != oNature:
700                                                                 for j in range(i):
701                                                                         if (natures[j] & oNature) != 0:
702                                                                                 visitNext = 1
703                                                                                 break
704                                                                 if visitNext != 0:
705                                                                         break    
706                                                         count = count+1
707                                                         winner = it.object
708                                                 it.increment()
709                                         if count != 1:
710                                                 winner = None
711                                         break
712                 return winner
713