extract_curves 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) 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/cstr.c +82 -0
  18. data/ruby_ext/pav/cstr.h +17 -0
  19. data/ruby_ext/pav/extconf.rb +22 -0
  20. data/ruby_ext/pav/pav.c +162 -0
  21. data/ruby_ext/pav/pgtk.c +40 -0
  22. data/ruby_ext/pav/pgtk.h +14 -0
  23. data/ruby_ext/pav/pix.c +806 -0
  24. data/ruby_ext/pav/pix.h +236 -0
  25. data/ruby_ext/pav/t.rb +35 -0
  26. data/ruby_ext/pav/t1.rb +35 -0
  27. data/ruby_libs/CVS/Entries +1 -0
  28. data/ruby_libs/CVS/Repository +1 -0
  29. data/ruby_libs/CVS/Root +1 -0
  30. data/ruby_libs/pav/CVS/Entries +20 -0
  31. data/ruby_libs/pav/CVS/Repository +1 -0
  32. data/ruby_libs/pav/CVS/Root +1 -0
  33. data/ruby_libs/pav/attr_cache.rb +211 -0
  34. data/ruby_libs/pav/attr_cache.t1.rb +32 -0
  35. data/ruby_libs/pav/cache.rb +31 -0
  36. data/ruby_libs/pav/dbg_log.rb +458 -0
  37. data/ruby_libs/pav/floatsio.rb +53 -0
  38. data/ruby_libs/pav/generator_cache.rb +165 -0
  39. data/ruby_libs/pav/gtk/CVS/Entries +4 -0
  40. data/ruby_libs/pav/gtk/CVS/Repository +1 -0
  41. data/ruby_libs/pav/gtk/CVS/Root +1 -0
  42. data/ruby_libs/pav/gtk/button.rb +130 -0
  43. data/ruby_libs/pav/gtk/icons.rb +87 -0
  44. data/ruby_libs/pav/gtk/toolbar.rb +192 -0
  45. data/ruby_libs/pav/heap.rb +54 -0
  46. data/ruby_libs/pav/icons/CVS/Entries +17 -0
  47. data/ruby_libs/pav/icons/CVS/Repository +1 -0
  48. data/ruby_libs/pav/icons/CVS/Root +1 -0
  49. data/ruby_libs/pav/icons/alt_handle.xcf +0 -0
  50. data/ruby_libs/pav/icons/alt_handle.xpm +3832 -0
  51. data/ruby_libs/pav/icons/alt_handle_hover.xcf +0 -0
  52. data/ruby_libs/pav/icons/alt_handle_hover.xpm +3368 -0
  53. data/ruby_libs/pav/icons/alt_handle_pressed.xcf +0 -0
  54. data/ruby_libs/pav/icons/alt_handle_pressed.xpm +3828 -0
  55. data/ruby_libs/pav/icons/extract_curves/CVS/Entries +6 -0
  56. data/ruby_libs/pav/icons/extract_curves/CVS/Repository +1 -0
  57. data/ruby_libs/pav/icons/extract_curves/CVS/Root +1 -0
  58. data/ruby_libs/pav/icons/extract_curves/extract_curves-icon-rgb.ppm +14 -0
  59. data/ruby_libs/pav/icons/extract_curves/extract_curves-logo-rgb.gif +0 -0
  60. data/ruby_libs/pav/icons/extract_curves/extract_curves-logo-rgb.xcf +0 -0
  61. data/ruby_libs/pav/icons/extract_curves/trace_mark.xcf +0 -0
  62. data/ruby_libs/pav/icons/extract_curves/trace_mark.xpm +38 -0
  63. data/ruby_libs/pav/icons/handle.xcf +0 -0
  64. data/ruby_libs/pav/icons/handle.xpm +213 -0
  65. data/ruby_libs/pav/icons/next.xpm +29 -0
  66. data/ruby_libs/pav/icons/next_hover.xpm +315 -0
  67. data/ruby_libs/pav/icons/next_pressed.xpm +144 -0
  68. data/ruby_libs/pav/icons/prev.xpm +29 -0
  69. data/ruby_libs/pav/icons/prev_hover.xpm +315 -0
  70. data/ruby_libs/pav/icons/prev_pressed.xpm +144 -0
  71. data/ruby_libs/pav/icons/vnext.xpm +29 -0
  72. data/ruby_libs/pav/icons/vprev.xpm +29 -0
  73. data/ruby_libs/pav/numeric/CVS/Entries +2 -0
  74. data/ruby_libs/pav/numeric/CVS/Repository +1 -0
  75. data/ruby_libs/pav/numeric/CVS/Root +1 -0
  76. data/ruby_libs/pav/numeric/ext.rb +13 -0
  77. data/ruby_libs/pav/pav_find.rb +90 -0
  78. data/ruby_libs/pav/pix.rb +402 -0
  79. data/ruby_libs/pav/pix/CVS/Entries +11 -0
  80. data/ruby_libs/pav/pix/CVS/Repository +1 -0
  81. data/ruby_libs/pav/pix/CVS/Root +1 -0
  82. data/ruby_libs/pav/pix/aapix.rb +378 -0
  83. data/ruby_libs/pav/pix/blob.rb +543 -0
  84. data/ruby_libs/pav/pix/circle.rb +73 -0
  85. data/ruby_libs/pav/pix/contour.rb +644 -0
  86. data/ruby_libs/pav/pix/contour/CVS/Entries +5 -0
  87. data/ruby_libs/pav/pix/contour/CVS/Repository +1 -0
  88. data/ruby_libs/pav/pix/contour/CVS/Root +1 -0
  89. data/ruby_libs/pav/pix/contour/calc_situations.rb +9 -0
  90. data/ruby_libs/pav/pix/contour/carp_calc.rb +212 -0
  91. data/ruby_libs/pav/pix/contour/situations.dmp +0 -0
  92. data/ruby_libs/pav/pix/contour/situations.rb +21 -0
  93. data/ruby_libs/pav/pix/curve.rb +1508 -0
  94. data/ruby_libs/pav/pix/img_obj.rb +751 -0
  95. data/ruby_libs/pav/pix/node.rb +712 -0
  96. data/ruby_libs/pav/pix/node_grp.rb +853 -0
  97. data/ruby_libs/pav/pix/shaved_core.rb +534 -0
  98. data/ruby_libs/pav/pix/subpix.rb +212 -0
  99. data/ruby_libs/pav/rand_accessible.rb +16 -0
  100. data/ruby_libs/pav/rangeset.rb +63 -0
  101. data/ruby_libs/pav/search.rb +210 -0
  102. data/ruby_libs/pav/set.rb +20 -0
  103. data/ruby_libs/pav/string/CVS/Entries +6 -0
  104. data/ruby_libs/pav/string/CVS/Repository +1 -0
  105. data/ruby_libs/pav/string/CVS/Root +1 -0
  106. data/ruby_libs/pav/string/bits.rb +523 -0
  107. data/ruby_libs/pav/string/ext.rb +58 -0
  108. data/ruby_libs/pav/string/observable.rb +155 -0
  109. data/ruby_libs/pav/string/text.rb +79 -0
  110. data/ruby_libs/pav/string/words.rb +42 -0
  111. data/ruby_libs/pav/sub_arr.rb +55 -0
  112. data/ruby_libs/pav/traced_obj.rb +79 -0
  113. metadata +161 -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