extract_curves 0.0.1-i586-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. data/CVS/Entries +4 -0
  2. data/CVS/Repository +1 -0
  3. data/CVS/Root +1 -0
  4. data/bin/CVS/Entries +5 -0
  5. data/bin/CVS/Repository +1 -0
  6. data/bin/CVS/Root +1 -0
  7. data/bin/ec_rect2polar.rb +22 -0
  8. data/bin/ec_rev_lines.rb +5 -0
  9. data/bin/ec_sph_area.rb +30 -0
  10. data/bin/extract_curves.rb +2145 -0
  11. data/ruby_ext/CVS/Entries +1 -0
  12. data/ruby_ext/CVS/Repository +1 -0
  13. data/ruby_ext/CVS/Root +1 -0
  14. data/ruby_ext/pav/CVS/Entries +14 -0
  15. data/ruby_ext/pav/CVS/Repository +1 -0
  16. data/ruby_ext/pav/CVS/Root +1 -0
  17. data/ruby_ext/pav/extconf.rb +22 -0
  18. data/ruby_ext/pav/pav.so +0 -0
  19. data/ruby_libs/CVS/Entries +1 -0
  20. data/ruby_libs/CVS/Repository +1 -0
  21. data/ruby_libs/CVS/Root +1 -0
  22. data/ruby_libs/pav/CVS/Entries +20 -0
  23. data/ruby_libs/pav/CVS/Repository +1 -0
  24. data/ruby_libs/pav/CVS/Root +1 -0
  25. data/ruby_libs/pav/attr_cache.rb +211 -0
  26. data/ruby_libs/pav/attr_cache.t1.rb +32 -0
  27. data/ruby_libs/pav/cache.rb +31 -0
  28. data/ruby_libs/pav/dbg_log.rb +458 -0
  29. data/ruby_libs/pav/floatsio.rb +53 -0
  30. data/ruby_libs/pav/generator_cache.rb +165 -0
  31. data/ruby_libs/pav/gtk/CVS/Entries +4 -0
  32. data/ruby_libs/pav/gtk/CVS/Repository +1 -0
  33. data/ruby_libs/pav/gtk/CVS/Root +1 -0
  34. data/ruby_libs/pav/gtk/button.rb +130 -0
  35. data/ruby_libs/pav/gtk/icons.rb +87 -0
  36. data/ruby_libs/pav/gtk/toolbar.rb +192 -0
  37. data/ruby_libs/pav/heap.rb +54 -0
  38. data/ruby_libs/pav/icons/CVS/Entries +17 -0
  39. data/ruby_libs/pav/icons/CVS/Repository +1 -0
  40. data/ruby_libs/pav/icons/CVS/Root +1 -0
  41. data/ruby_libs/pav/icons/alt_handle.xpm +3832 -0
  42. data/ruby_libs/pav/icons/alt_handle_hover.xpm +3368 -0
  43. data/ruby_libs/pav/icons/alt_handle_pressed.xpm +3828 -0
  44. data/ruby_libs/pav/icons/extract_curves/CVS/Entries +6 -0
  45. data/ruby_libs/pav/icons/extract_curves/CVS/Repository +1 -0
  46. data/ruby_libs/pav/icons/extract_curves/CVS/Root +1 -0
  47. data/ruby_libs/pav/icons/extract_curves/extract_curves-icon-rgb.ppm +14 -0
  48. data/ruby_libs/pav/icons/extract_curves/extract_curves-logo-rgb.gif +0 -0
  49. data/ruby_libs/pav/icons/extract_curves/trace_mark.xpm +38 -0
  50. data/ruby_libs/pav/icons/handle.xpm +213 -0
  51. data/ruby_libs/pav/icons/next.xpm +29 -0
  52. data/ruby_libs/pav/icons/next_hover.xpm +315 -0
  53. data/ruby_libs/pav/icons/next_pressed.xpm +144 -0
  54. data/ruby_libs/pav/icons/prev.xpm +29 -0
  55. data/ruby_libs/pav/icons/prev_hover.xpm +315 -0
  56. data/ruby_libs/pav/icons/prev_pressed.xpm +144 -0
  57. data/ruby_libs/pav/icons/vnext.xpm +29 -0
  58. data/ruby_libs/pav/icons/vprev.xpm +29 -0
  59. data/ruby_libs/pav/numeric/CVS/Entries +2 -0
  60. data/ruby_libs/pav/numeric/CVS/Repository +1 -0
  61. data/ruby_libs/pav/numeric/CVS/Root +1 -0
  62. data/ruby_libs/pav/numeric/ext.rb +13 -0
  63. data/ruby_libs/pav/pav_find.rb +90 -0
  64. data/ruby_libs/pav/pix/CVS/Entries +11 -0
  65. data/ruby_libs/pav/pix/CVS/Repository +1 -0
  66. data/ruby_libs/pav/pix/CVS/Root +1 -0
  67. data/ruby_libs/pav/pix/aapix.rb +378 -0
  68. data/ruby_libs/pav/pix/blob.rb +543 -0
  69. data/ruby_libs/pav/pix/circle.rb +73 -0
  70. data/ruby_libs/pav/pix/contour/CVS/Entries +5 -0
  71. data/ruby_libs/pav/pix/contour/CVS/Repository +1 -0
  72. data/ruby_libs/pav/pix/contour/CVS/Root +1 -0
  73. data/ruby_libs/pav/pix/contour/calc_situations.rb +9 -0
  74. data/ruby_libs/pav/pix/contour/carp_calc.rb +212 -0
  75. data/ruby_libs/pav/pix/contour/situations.dmp +0 -0
  76. data/ruby_libs/pav/pix/contour/situations.rb +21 -0
  77. data/ruby_libs/pav/pix/contour.rb +644 -0
  78. data/ruby_libs/pav/pix/curve.rb +1508 -0
  79. data/ruby_libs/pav/pix/img_obj.rb +751 -0
  80. data/ruby_libs/pav/pix/node.rb +712 -0
  81. data/ruby_libs/pav/pix/node_grp.rb +853 -0
  82. data/ruby_libs/pav/pix/shaved_core.rb +534 -0
  83. data/ruby_libs/pav/pix/subpix.rb +212 -0
  84. data/ruby_libs/pav/pix.rb +402 -0
  85. data/ruby_libs/pav/rand_accessible.rb +16 -0
  86. data/ruby_libs/pav/rangeset.rb +63 -0
  87. data/ruby_libs/pav/search.rb +210 -0
  88. data/ruby_libs/pav/set.rb +20 -0
  89. data/ruby_libs/pav/string/CVS/Entries +6 -0
  90. data/ruby_libs/pav/string/CVS/Repository +1 -0
  91. data/ruby_libs/pav/string/CVS/Root +1 -0
  92. data/ruby_libs/pav/string/bits.rb +523 -0
  93. data/ruby_libs/pav/string/ext.rb +58 -0
  94. data/ruby_libs/pav/string/observable.rb +155 -0
  95. data/ruby_libs/pav/string/text.rb +79 -0
  96. data/ruby_libs/pav/string/words.rb +42 -0
  97. data/ruby_libs/pav/sub_arr.rb +55 -0
  98. data/ruby_libs/pav/traced_obj.rb +79 -0
  99. metadata +147 -0
@@ -0,0 +1,712 @@
1
+ require 'pav/pix'
2
+ require 'pav/heap'
3
+ require 'pav/pix/aapix'
4
+
5
+ module PPix
6
+
7
+ class NoReversePathwayError < RuntimeError
8
+ attr_accessor :pathway, :start_node
9
+
10
+ def initialize(pathway, start_node=nil)
11
+ @pathway = pathway
12
+ @start_node = start_node
13
+ end
14
+ end
15
+
16
+ class NoReverseLinkError < NoReversePathwayError
17
+ end
18
+
19
+ class NoReverseConnError < NoReversePathwayError
20
+ end
21
+
22
+ class NodeLink
23
+ attr_reader :node, :conn_i, :c_reverse
24
+
25
+ def initialize(node, conn_i)
26
+ @node = node
27
+ @conn_i = conn_i
28
+ @c_reverse = nil
29
+ end
30
+
31
+ def ==(link)
32
+ @node.node_eql?(link.node) && @conn_i == link.conn_i
33
+ end
34
+
35
+ def reverse
36
+ return @c_reverse if @c_reverse
37
+ conn = @node.conns[@conn_i]
38
+ exit = conn.exit
39
+ r_conn = conn.reverse(@node)
40
+ exit.conns.each_with_index { |cn, cn_i|
41
+ if cn == r_conn
42
+ return @c_reverse = NodeLink.new(exit, cn_i)
43
+ end
44
+ }
45
+ raise NoReverseLinkError.new(self, @node),
46
+ #"#{self.class.name}.reverse: No rev. link: " +
47
+ "#{self}; conn.: #{node.conns[@conn_i]}; r_conn: #{r_conn}" +
48
+ (exit.conns.length < 50 ? '; '+NodeConn.conns_to_s(
49
+ exit.conns) : '')
50
+ nil
51
+ end
52
+
53
+ def expand_to_xy_path
54
+ @node.conns[@conn_i].path.expand_to_xy_path
55
+ end
56
+
57
+ def exit
58
+ @node.conns[@conn_i].exit
59
+ end
60
+
61
+ def length
62
+ @node.conns[@conn_i].length
63
+ end
64
+
65
+ def path
66
+ @node.conns[@conn_i].path
67
+ end
68
+
69
+ def conn
70
+ @node.conns[@conn_i]
71
+ end
72
+
73
+ def to_s(how=0)
74
+ "#{@node}-[#{@conn_i}]->" + (how >= 1 ?
75
+ @node.conns[@conn_i].exit.to_s : '')
76
+ end
77
+ end
78
+
79
+ class NodePath < Array
80
+ def ==(path2)
81
+ #$PDbgLog.sig_call(self.name + "#")
82
+ #$PDbgLog.puts_msg "self: #{self}; path2: #{path2}"
83
+ if self.length != path2.length
84
+ # $PDbgLog.sig_return
85
+ return false
86
+ end
87
+ self.each_with_index { |link, i|
88
+ return false if !link = path2.at(i) }
89
+ #$PDbgLog.sig_return
90
+ true
91
+ end
92
+
93
+ def +(path2)
94
+ self.dup.concat(path2)
95
+ end
96
+
97
+ def get_length
98
+ res = 0
99
+ self.each { |link| res += link.length }
100
+ res
101
+ end
102
+
103
+ def entry
104
+ return nil if self.empty?
105
+ self.first.node
106
+ end
107
+
108
+ def exit
109
+ return nil if self.empty?
110
+ self.last.exit
111
+ end
112
+
113
+ alias_method :reverse_links, :reverse
114
+ alias_method :reverse_links!, :reverse!
115
+
116
+ def reverse
117
+ res = []
118
+ self.each_with_index { |link, i|
119
+ res[self.length-i] = link.reverse }
120
+ end
121
+
122
+ def reverse!
123
+ 0.upto(self.length-1) { |i| self[i] = self[i].reverse }
124
+ super
125
+ end
126
+
127
+ def expand_to_xy_path
128
+ return [] if self.empty?
129
+ res = self.first.expand_to_xy_path
130
+ 1.upto(self.length-1) { |i|
131
+ res.concat(self.at(i).expand_to_xy_path) }
132
+ res
133
+ end
134
+
135
+ def to_s(how=1)
136
+ self.join(' ') << (how > 0 ? self.exit.to_s : '')
137
+ end
138
+
139
+ def each_node
140
+ for link in self
141
+ yield(link.node)
142
+ end
143
+ if (exit = self.exit)
144
+ yield(exit)
145
+ end
146
+ end
147
+ end
148
+
149
+ class XyPath < Array
150
+ def self.yx_path_to_s(path)
151
+ path.collect { |yx| "(#{yx[1]}, #{yx[0]})" }.join(" ")
152
+ end
153
+
154
+ def get_length
155
+ self.length - 1
156
+ end
157
+
158
+ alias_method :entry, :first
159
+ alias_method :exit, :last
160
+
161
+ def to_s
162
+ self.collect { |pix| pix.to_s }.join(" ")
163
+ end
164
+
165
+ def eql?(path2)
166
+ #$PDbgLog.sig_call(self.name + "#")
167
+ #$PDbgLog.puts_msg "path1: #{path1}; path2: #{path2}"
168
+ if self.length != path2.length
169
+ # $PDbgLog.sig_return
170
+ return false
171
+ end
172
+ self.each_with_index { |pix, i|
173
+ return false if pix.y != path2[i].y ||
174
+ pix.x != path2[i].x
175
+ }
176
+ #$PDbgLog.sig_return
177
+ true
178
+ end
179
+
180
+ def starts_with(pfx_path)
181
+ return false unless self.length >= pfx_path.length
182
+ pfx_path.each_with_index { |pix, i|
183
+ return false if pix.yx != self.at(i).yx }
184
+ true
185
+ end
186
+
187
+ def ends_with(sfx_path)
188
+ return false unless (ofs = self.length - sfx_path.length) >= 0
189
+ 0.upto(sfx_path.length-1) { |i|
190
+ return false if sfx_path.at(i).yx != self.at(ofs+i).yx }
191
+ true
192
+ end
193
+
194
+ def a_eql?(path2)
195
+ #$PDbgLog.sig_call(self.name + "#")
196
+ #$PDbgLog.puts_msg "self: #{self}; path2: #{path2}"
197
+ if self.length != path2.length
198
+ # $PDbgLog.sig_return
199
+ return false
200
+ end
201
+ self.each_with_index { |pix, i|
202
+ return false if !pix.a_eql?(path2.at(i)) }
203
+ #$PDbgLog.sig_return
204
+ true
205
+ end
206
+
207
+ def node_eql?(path2)
208
+ #$PDbgLog.sig_call(self.name + "#")
209
+ #$PDbgLog.puts_msg "self: #{self}; path2: #{path2}"
210
+ if self.length != path2.length
211
+ # $PDbgLog.sig_return
212
+ return false
213
+ end
214
+ self.each_with_index { |node, i|
215
+ return false if !node.a_eql?(path2.at(i)) }
216
+ #$PDbgLog.sig_return
217
+ true
218
+ end
219
+
220
+ alias_method :==, :node_eql?
221
+
222
+ def a_starts_with(pfx_path)
223
+ return false unless self.length >= spath.length
224
+ self.each_with_index { |pix, i|
225
+ return false if !pix.a_eql?(pfx_path.at(i)) }
226
+ true
227
+ end
228
+
229
+ def a_ends_with(sfx_path)
230
+ return false unless (ofs = self.length - sfx_path.length) >= 0
231
+ 0.upto(sfx_path.length-1) { |i|
232
+ return false if !sfx_path.at(i).a_eql?(self.at(ofs+i)) }
233
+ true
234
+ end
235
+
236
+ def dup
237
+ XyPath.new(self)
238
+ end
239
+
240
+ def concat(path)
241
+ super(path[1, path.length-1])
242
+ self
243
+ end
244
+
245
+ def +(path)
246
+ self.dup.concat(path[1, path.length-1])
247
+ end
248
+
249
+ alias_method :expand_to_xy_path, :dup
250
+
251
+ def xy_nodes
252
+ self[1, self.length-1]
253
+ end
254
+ end
255
+
256
+ class NodeConn
257
+ attr_reader :exit, :length
258
+ attr_accessor :path
259
+
260
+ def self.conns_to_s(conns)
261
+ conns.collect {|cn| cn.to_s}.join(', ')
262
+ end
263
+
264
+ def initialize(exit, length)
265
+ @exit = exit
266
+ @length = length
267
+ raise ArgumentError, "Conn.'s exit must be an AaXyNode!" unless
268
+ @exit.kind_of?(AaXyNode)
269
+ raise ArgumentError, "Conn.'s length must be numeric!" unless
270
+ @length.kind_of?(Numeric)
271
+ end
272
+
273
+ def reverse(conn_0)
274
+ res = NodeConn.new(conn_0, length)
275
+ res.path = path.reverse
276
+ res
277
+ end
278
+
279
+ def max_depth(to_parent_conn_i, visited={})
280
+ return @c_max_depth if @c_max_depth
281
+ @c_max_depth = @length +
282
+ @exit.dir_max_depth(to_parent_conn_i, visited)
283
+ end
284
+
285
+ def to_s(how=0)
286
+ "<-#{@length}->#{@exit}" + (how<1 ? '' : ': ' + self.path.to_s)
287
+ end
288
+
289
+ def eql?(conn)
290
+ @exit.node_eql?(conn.exit) && @length == conn.length &&
291
+ @path == conn.path
292
+ end
293
+
294
+ alias_method :==, :eql?
295
+ end
296
+
297
+ class AaXyNode < AaXy
298
+ attr_reader :conns, :c_rev_conns
299
+
300
+ def initialize(ax, ay, conns)
301
+ super(ax, ay)
302
+ @conns = conns
303
+ @c_rev_conns = []
304
+ end
305
+
306
+ def rev_conn_idx(conn_i)
307
+ if (tmp = @c_rev_conns[conn_i])
308
+ return tmp
309
+ end
310
+ conn = @conns[conn_i]
311
+ l = conn.exit
312
+ rev_conn = conn.reverse(self)
313
+ l.conns.each_with_index { |cn, cn_i|
314
+ return cn_i if cn == rev_conn }
315
+ raise NoReverseConnError.new(conn, self),
316
+ "#{self.coords_to_s} #{@conns[conn_i].to_s(2)}!"
317
+ nil
318
+ end
319
+
320
+ def to_parent_conn_idx(conn_i)
321
+ begin
322
+ self.rev_conn_idx(conn_i)
323
+ rescue NoReverseConnError
324
+ if self.node_eql?(@conns[conn_i].exit)
325
+ @c_rev_conns[conn_i] = conn_i
326
+ else
327
+ raise
328
+ end
329
+ end
330
+ end
331
+
332
+ def clear_rev_conns_cache
333
+ @c_rev_conns.clear
334
+ end
335
+
336
+ def delete_conn(conn_i)
337
+ @conns.delete_at(conn_i)
338
+ @c_rev_conns.delete_at(conn_i)
339
+ end
340
+
341
+ def conns_to_s
342
+ NodeConn.conns_to_s(@conns)
343
+ end
344
+
345
+ alias_method :node_eql?, :a_eql?
346
+
347
+ def each_link
348
+ @conns.each_index { |conn_i| yield(NodeLink.new(self, conn_i)) }
349
+ end
350
+
351
+ def get_min_lp_n_len(max_len=1.0/0.0)
352
+ #$PDbgLog.sig_call(self)
353
+ #$PDbgLog.print_msg self.coords_to_s + ", max_len=#{max_len}: "
354
+ p1, p2, len = *PSearch.first_norep_loop(self, max_len, max_len,
355
+ proc { |p| p.a_yx }) { |node, lev|
356
+ res = []
357
+ node.conns.each_with_index { |cn, cn_i|
358
+ res << [cn.exit,NodeLink.new(node,cn_i),lev+cn.length] }
359
+ res
360
+ }
361
+ unless p1
362
+ #$PDbgLog.sig_return
363
+ return [nil, nil]
364
+ end
365
+ #$PDbgLog.puts_msg 'p1: ' + p1.collect { |link|
366
+ # link ? link.to_s(1) : link.inspect }.join(' ')
367
+ #$PDbgLog.puts_msg 'p2: ' + p2.collect { |link|
368
+ # link ? link.to_s(1) : link.inspect }.join(' ')
369
+ lp = NodePath.new
370
+ p2.reverse_each { |link| lp << link }
371
+ p1.each { |link| lp << link.reverse }
372
+ #$PDbgLog.sig_return(lp)
373
+ [lp, len]
374
+ end
375
+
376
+ def dup_with_map(map)
377
+ if (tmp = map[self])
378
+ return tmp
379
+ end
380
+ res = map[self] = AaXyNod.new(self.ax, self.ay, conns=[])
381
+ @conns.each { |conn|
382
+ new_conn = NodeConn.new(conn.exit.dup_with_map(map),
383
+ conn.length)
384
+ new_conn.path = conn.path
385
+ conns << new_conn
386
+ }
387
+ res
388
+ end
389
+
390
+ def dup_graph
391
+ self.dup_with_map({})
392
+ end
393
+
394
+ def conn_max_depth(conn_i)
395
+ begin
396
+ rev_conn_i = self.rev_conn_idx(conn_i)
397
+ rescue NoReversePathwayError
398
+ rev_conn_i = -1
399
+ end
400
+ @conns[conn_i].max_depth(rev_conn_i)
401
+ end
402
+
403
+ def dir_max_depth(to_parent_conn_i, visited)
404
+ #$PDbgLog.sig_call(self)
405
+ max_depth = 0
406
+ visited[self] = true
407
+ @conns.each_with_index { |conn, conn_i|
408
+ next if to_parent_conn_i == conn_i
409
+ if visited.include?(conn.exit)
410
+ max_depth = 1.0/0.0
411
+ break
412
+ end
413
+ tmp = conn.max_depth(self.rev_conn_idx(conn_i), visited)
414
+ max_depth = tmp if tmp > max_depth
415
+ }
416
+ #$PDbgLog.sig_return
417
+ max_depth
418
+ end
419
+
420
+ def graph_each_conn_i(visited={}, &block)
421
+ if visited.include?(self)
422
+ vis_conns = visited[self]
423
+ else
424
+ vis_conns = visited[self] = []
425
+ end
426
+ @conns.each_with_index { |conn, conn_i|
427
+ unless vis_conns[conn_i]
428
+ yield(self, conn_i)
429
+ vis_conns[conn_i] = true
430
+ begin
431
+ visited[conn.exit] = [] unless
432
+ visited.include?(conn.exit)
433
+ visited[conn.exit][self.rev_conn_idx(conn_i)] = true
434
+ rescue NoReversePathwayError
435
+ end
436
+ conn.exit.graph_each_conn_i(visited, &block)
437
+ end
438
+ }
439
+ end
440
+
441
+ def graph_each_node(visited={}, &block)
442
+ return if visited.include?(self)
443
+ visited[self] = true
444
+ yield(self)
445
+ @conns.each {|conn| conn.exit.graph_each_node(visited, &block) }
446
+ end
447
+
448
+ def to_s(how=0)
449
+ res = self.coords_to_s
450
+ return res if how < 1
451
+ res.concat('+conns: ')
452
+ @conns.each_with_index { |conn, conn_i|
453
+ res.concat("[#{conn_i}]#{conn.to_s(how-1)}; ")
454
+ }
455
+ res[-2,2] = ''
456
+ res
457
+ end
458
+
459
+ def graph_to_s
460
+ res = ''
461
+ self.graph_each_conn_i { |node, conn_i|
462
+ res.concat(node.to_s + ": [#{conn_i}]#{node.conns[
463
+ conn_i].to_s(2)}\n")
464
+ }
465
+ res
466
+ end
467
+ end
468
+
469
+ class NodeCalcPCachePathIter
470
+ attr_accessor :path_cache, :node
471
+
472
+ def initialize(path_cache=nil, node=nil)
473
+ @path_cache = path_cache
474
+ @node = node
475
+ end
476
+
477
+ def pop
478
+ to_link = path_cache[@node][1]
479
+ @node = to_link ? to_link.node : nil
480
+ to_link
481
+ end
482
+ end
483
+
484
+ class NodeCalc
485
+ attr_reader :node, :c_paths
486
+ attr_accessor :link_filter
487
+
488
+ def initialize(node)
489
+ @node = node
490
+ @c_paths = {}
491
+ @link_filter = nil
492
+ end
493
+
494
+ def find_shortest_path_to_node(dest, max_lev=1.0/0.0,
495
+ path_cache=@c_paths)
496
+ #$PDbgLog.sig_call(self)
497
+ if max_lev < 0
498
+ #$PDbgLog.sig_return("max_lev < 0: nil")
499
+ return nil
500
+ end
501
+ path_cache = {} unless path_cache
502
+ if @link_filter
503
+ #$PDbgLog.sig_return
504
+ return self.find_shortest_path_to_node_with_link_filter(
505
+ dest, max_lev, path_cache)
506
+ end
507
+ path_cache[@node] = [0, nil] unless path_cache.include?(@node)&&
508
+ path_cache[@node][0] <= 0 && path_cache[@node][1] == nil
509
+ tail = PMinHeap.new { |a,b| a[1] <=> b[1] }
510
+ path_cache.each_pair { |node, frm| tail.push([node, frm[0]]) }
511
+ while !tail.empty?
512
+ node, lev = *tail.pop
513
+ next if path_cache.include?(node) &&
514
+ path_cache[node][0] < lev
515
+ if path_cache.include?(dest)
516
+ res = NodePath.new; node = dest
517
+ to_link = path_cache[node][1]
518
+ while to_link
519
+ res << to_link
520
+ to_link = path_cache[to_link.node][1]
521
+ end
522
+ res.reverse_links!
523
+ #$PDbgLog.sig_return(res.inspect)
524
+ return res
525
+ end
526
+ node.conns.each_with_index { |conn,conn_i| l = conn.exit
527
+ if (l_lev = lev+conn.length) <= max_lev &&
528
+ (!path_cache.include?(l) || path_cache[l][0] > l_lev)
529
+ tail.push([l, l_lev])
530
+ path_cache[l]=[l_lev,NodeLink.new(node,conn_i)]
531
+ end
532
+ }
533
+ end
534
+ #$PDbgLog.sig_return("nil")
535
+ nil
536
+ end
537
+
538
+ def find_shortest_path_to_node_with_link_filter(dest, max_lev,
539
+ path_cache)
540
+ #$PDbgLog.sig_call(self)
541
+ path_cache[@node] = [0, nil] unless path_cache.include?(@node)&&
542
+ path_cache[@node][0] <= 0 && path_cache[@node][1] == nil
543
+ tail = PMinHeap.new { |a,b| a[1] <=> b[1] }
544
+ path_cache.each_pair { |node, frm| tail.push([node, frm[0]]) }
545
+ #$PDbgLog.print_msg "node#{@node.coords_to_s}, dest#{dest.
546
+ # coords_to_s}, max_lev=#{max_lev}: "
547
+ while !tail.empty?
548
+ node, lev = *tail.pop
549
+ # $PDbgLog.print_msg "node#{node.coords_to_s},lev=#{lev} "
550
+ next if path_cache.include?(node) &&
551
+ path_cache[node][0] < lev
552
+ if path_cache.include?(dest)
553
+ res = NodePath.new; node = dest
554
+ to_link = path_cache[node][1]
555
+ while to_link
556
+ res << to_link
557
+ to_link = path_cache[to_link.node][1]
558
+ end
559
+ res.reverse_links!
560
+ #$PDbgLog.sig_return('found ' + res.to_s + '.')
561
+ return res
562
+ end
563
+ node.conns.each_with_index { |conn,conn_i| l = conn.exit
564
+ #$PDbgLog.print_msg "conn #{conn_i}: #{conn} "
565
+ if (l_lev = lev+conn.length) <= max_lev &&
566
+ (!path_cache.include?(l) || path_cache[l][0]>l_lev) &&
567
+ @link_filter.call(link=NodeLink.new(node,conn_i))
568
+ tail.push([l, l_lev])
569
+ path_cache[l]=[l_lev, link]
570
+ end
571
+ }
572
+ end
573
+ #$PDbgLog.sig_return("no path found.")
574
+ nil
575
+ end
576
+
577
+ def self.path_cache_to_s(path_cache)
578
+ "{#{path_cache.keys.to_a.sort.collect{|k| k.to_s + "=>[#{
579
+ path_cache[k][0]}, " + (path_cache[k][1] ?
580
+ path_cache[k][1].to_s : 'nil') + "]"}.join(", ")}}"
581
+ end
582
+
583
+ def self.path_cache_get_path_to_self(node, path_cache)
584
+ to_link = path_cache[node][1]
585
+ res = NodePath.new
586
+ while !to_link.node.node_eql?(node)
587
+ res << to_link
588
+ to_link = path_cache[to_link.node]
589
+ end
590
+ res << to_link
591
+ res.reverse_links!
592
+ end
593
+
594
+ def self.path_cache_get_path(node, path_cache)
595
+ #$PDbgLog.sig_call(self)
596
+ #$PDbgLog.print_msg "node#{node}, path_cache: #{self.
597
+ # path_cache_to_s(path_cache)}: "
598
+ to_link = path_cache[node][1]
599
+ res = NodePath.new
600
+ while to_link
601
+ res << to_link
602
+ to_link = path_cache[to_link.node][1]
603
+ end
604
+ res.reverse_links!
605
+ #$PDbgLog.sig_return(res.to_s(1))
606
+ res
607
+ end
608
+
609
+ def find_first_path_to(dest, max_lev=1.0/0.0, path_cache=nil)
610
+ if max_lev < 0
611
+ return nil
612
+ end
613
+ if @link_filter
614
+ return self.find_first_path_to_with_link_filter(dest,
615
+ max_lev, path_cache)
616
+ end
617
+ if dest.kind_of?(Proc)
618
+ dest_proc = dest
619
+ else
620
+ dest_proc = proc {|node,lev| dest.node_eql?(node)}
621
+ end
622
+ tail = PMinHeap.new { |frm1,frm2| frm1[1] <=> frm2[1] }
623
+ unless path_cache
624
+ path_cache = @c_paths
625
+ unless dest.kind_of?(Proc)
626
+ return NodeCalc.path_cache_get_path(dest,
627
+ path_cache) if path_cache.include?(dest)
628
+ end
629
+ path_cache.each_pair { |node, frm|
630
+ tail.push([node, frm[0]]) }
631
+ end
632
+ path_cache[@node] = [0, nil]
633
+ tail.push([@node, 0])
634
+ while !tail.empty?
635
+ node, lev = *tail.pop
636
+ next if path_cache.include?(node) &&
637
+ path_cache[node][0] < lev
638
+ if dest_proc.call(node, lev)
639
+ res = NodeCalc.path_cache_get_path(node,
640
+ path_cache)
641
+ return res
642
+ end
643
+ node.conns.each_with_index { |conn,conn_i| l = conn.exit
644
+ if (l_lev = lev + conn.length) <= max_lev &&
645
+ (!path_cache.include?(l) || path_cache[l][0] > l_lev)
646
+ tail.push([l, l_lev])
647
+ path_cache[l]=[l_lev,NodeLink.new(node,conn_i)]
648
+ end
649
+ }
650
+ end
651
+ nil
652
+ end
653
+
654
+ def find_first_path_to_with_link_filter(dest, max_lev, path_cache=nil)
655
+ #$PDbgLog.sig_call(self)
656
+ #$PDbgLog.print_msg "dest:#{dest}, max_lev=#{max_lev}"
657
+ if dest.kind_of?(Proc)
658
+ dest_proc = dest
659
+ else
660
+ dest_proc = proc {|node,lev| dest.node_eql?(node)}
661
+ end
662
+ tail = PMinHeap.new { |frm1,frm2| frm1[1] <=> frm2[1] }
663
+ unless path_cache
664
+ path_cache = @c_paths
665
+ if !dest.kind_of?(Proc) && path_cache.include?(dest)
666
+ #$PDbgLog.sig_return(': cached.')
667
+ return NodeCalc.path_cache_get_path(dest,
668
+ path_cache)
669
+ end
670
+ path_cache.each_pair { |node, frm|
671
+ tail.push([node, frm[0]]) }
672
+ end
673
+ path_cache[@node] = [0, nil]
674
+ tail.push([@node, 0])
675
+ while !tail.empty?
676
+ node, lev = *tail.pop
677
+ next if path_cache.include?(node) &&
678
+ path_cache[node][0] < lev
679
+ #$PDbgLog.print_msg "node#{node},lev=#{lev} "
680
+ if dest_proc.call(node, lev)
681
+ res = NodeCalc.path_cache_get_path(node,
682
+ path_cache)
683
+ #$PDbgLog.sig_return('Done.')
684
+ return res
685
+ end
686
+ node.conns.each_with_index { |conn,conn_i| l = conn.exit
687
+ if (l_lev = lev + conn.length) <= max_lev &&
688
+ (!path_cache.include?(l) || path_cache[l][0]>l_lev) &&
689
+ @link_filter.call(link=NodeLink.new(node,conn_i))
690
+ tail.push([l, l_lev])
691
+ path_cache[l] = [l_lev, link]
692
+ end
693
+ }
694
+ end
695
+ #$PDbgLog.sig_return(': nil')
696
+ nil
697
+ end
698
+
699
+ def kill_path_cache!
700
+ @c_paths.clear
701
+ end
702
+
703
+ def path_cache_each_path
704
+ iter = NodeCalcPCachePathIter.new(@c_paths)
705
+ @c_paths.each_key { |node|
706
+ iter.node = node
707
+ yield(iter)
708
+ }
709
+ end
710
+ end
711
+
712
+ end