extract-curves 0.1.1-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. data/Changelog +21 -0
  2. data/bin/ec_rect2polar +22 -0
  3. data/bin/ec_rect2polar.rb +22 -0
  4. data/bin/ec_rev_lines +5 -0
  5. data/bin/ec_rev_lines.rb +5 -0
  6. data/bin/ec_sph_area +30 -0
  7. data/bin/ec_sph_area.rb +30 -0
  8. data/bin/extract_curves +1670 -0
  9. data/bin/extract_curves.rb +1670 -0
  10. data/ruby_ext/pav/extconf.rb +22 -0
  11. data/ruby_ext/pav/pav.dll +0 -0
  12. data/ruby_libs/pav/attr_cache.rb +211 -0
  13. data/ruby_libs/pav/attr_cache.t1.rb +32 -0
  14. data/ruby_libs/pav/cache.rb +31 -0
  15. data/ruby_libs/pav/collection/std.rb +58 -0
  16. data/ruby_libs/pav/dbg_log.rb +458 -0
  17. data/ruby_libs/pav/floatsio.rb +53 -0
  18. data/ruby_libs/pav/generator_cache.rb +165 -0
  19. data/ruby_libs/pav/graph/node.rb +602 -0
  20. data/ruby_libs/pav/graph/node_grp.rb +865 -0
  21. data/ruby_libs/pav/gtk.rb +6 -0
  22. data/ruby_libs/pav/gtk/button.rb +118 -0
  23. data/ruby_libs/pav/gtk/dialog.rb +29 -0
  24. data/ruby_libs/pav/gtk/guiobj.rb +772 -0
  25. data/ruby_libs/pav/gtk/icons.rb +124 -0
  26. data/ruby_libs/pav/gtk/rulers.rb +264 -0
  27. data/ruby_libs/pav/gtk/toolbar.rb +189 -0
  28. data/ruby_libs/pav/guiobj.rb +2 -0
  29. data/ruby_libs/pav/guiobj/info_asm.rb +41 -0
  30. data/ruby_libs/pav/guiobj/method.rb +211 -0
  31. data/ruby_libs/pav/guiobj/obj.rb +134 -0
  32. data/ruby_libs/pav/guiobj/signals.rb +9 -0
  33. data/ruby_libs/pav/heap.rb +54 -0
  34. data/ruby_libs/pav/icons/alt_handle.xpm +3832 -0
  35. data/ruby_libs/pav/icons/alt_handle_hover.xpm +3368 -0
  36. data/ruby_libs/pav/icons/alt_handle_pressed.xpm +3828 -0
  37. data/ruby_libs/pav/icons/blob.gif +0 -0
  38. data/ruby_libs/pav/icons/contour.gif +0 -0
  39. data/ruby_libs/pav/icons/contour_carpet.gif +0 -0
  40. data/ruby_libs/pav/icons/curve.gif +0 -0
  41. data/ruby_libs/pav/icons/curve_carpet.gif +0 -0
  42. data/ruby_libs/pav/icons/expand_closed.xpm +1791 -0
  43. data/ruby_libs/pav/icons/expand_closed_hover.xpm +1775 -0
  44. data/ruby_libs/pav/icons/expand_open.xpm +1788 -0
  45. data/ruby_libs/pav/icons/expand_open_hover.xpm +1752 -0
  46. data/ruby_libs/pav/icons/extract_curves/extract_curves-icon-rgb.ppm +14 -0
  47. data/ruby_libs/pav/icons/extract_curves/extract_curves-logo-rgb.gif +0 -0
  48. data/ruby_libs/pav/icons/extract_curves/trace_mark.xpm +38 -0
  49. data/ruby_libs/pav/icons/handle.xpm +213 -0
  50. data/ruby_libs/pav/icons/loop.gif +0 -0
  51. data/ruby_libs/pav/icons/loop_carpet.gif +0 -0
  52. data/ruby_libs/pav/icons/next.xpm +29 -0
  53. data/ruby_libs/pav/icons/next_hover.xpm +315 -0
  54. data/ruby_libs/pav/icons/next_pressed.xpm +144 -0
  55. data/ruby_libs/pav/icons/prev.xpm +29 -0
  56. data/ruby_libs/pav/icons/prev_hover.xpm +315 -0
  57. data/ruby_libs/pav/icons/prev_pressed.xpm +144 -0
  58. data/ruby_libs/pav/icons/shaved-core.gif +0 -0
  59. data/ruby_libs/pav/icons/vnext.xpm +29 -0
  60. data/ruby_libs/pav/icons/vprev.xpm +29 -0
  61. data/ruby_libs/pav/numeric/ext.rb +21 -0
  62. data/ruby_libs/pav/patterns/hsep.gif +0 -0
  63. data/ruby_libs/pav/patterns/tnode.gif +0 -0
  64. data/ruby_libs/pav/patterns/tnode_w_link.gif +0 -0
  65. data/ruby_libs/pav/patterns/vlink.gif +0 -0
  66. data/ruby_libs/pav/patterns/vsep.gif +0 -0
  67. data/ruby_libs/pav/patterns/yg_hrope.xpm +492 -0
  68. data/ruby_libs/pav/patterns/yg_hrope_thick.xpm +1904 -0
  69. data/ruby_libs/pav/patterns/yg_hrope_thin.xpm +130 -0
  70. data/ruby_libs/pav/patterns/yg_tnode.xpm +180 -0
  71. data/ruby_libs/pav/patterns/yg_tnode_thick.xpm +615 -0
  72. data/ruby_libs/pav/patterns/yg_tnode_thin.xpm +55 -0
  73. data/ruby_libs/pav/patterns/yg_tnode_w_link.xpm +190 -0
  74. data/ruby_libs/pav/patterns/yg_tnode_w_link_thick.xpm +676 -0
  75. data/ruby_libs/pav/patterns/yg_tnode_w_link_thin.xpm +62 -0
  76. data/ruby_libs/pav/patterns/yg_vrope.xpm +563 -0
  77. data/ruby_libs/pav/patterns/yg_vrope_thick.xpm +2047 -0
  78. data/ruby_libs/pav/patterns/yg_vrope_thin.xpm +166 -0
  79. data/ruby_libs/pav/pav_find.rb +90 -0
  80. data/ruby_libs/pav/pix.rb +402 -0
  81. data/ruby_libs/pav/pix/aapix.rb +378 -0
  82. data/ruby_libs/pav/pix/blob.rb +678 -0
  83. data/ruby_libs/pav/pix/circle.rb +73 -0
  84. data/ruby_libs/pav/pix/contour.rb +676 -0
  85. data/ruby_libs/pav/pix/contour/calc_situations.rb +9 -0
  86. data/ruby_libs/pav/pix/contour/carp_calc.rb +212 -0
  87. data/ruby_libs/pav/pix/contour/situations.dmp +0 -0
  88. data/ruby_libs/pav/pix/contour/situations.rb +21 -0
  89. data/ruby_libs/pav/pix/curve.rb +1544 -0
  90. data/ruby_libs/pav/pix/img_obj.rb +865 -0
  91. data/ruby_libs/pav/pix/node.rb +159 -0
  92. data/ruby_libs/pav/pix/shaved_core.rb +697 -0
  93. data/ruby_libs/pav/pix/subpix.rb +212 -0
  94. data/ruby_libs/pav/rand_accessible.rb +16 -0
  95. data/ruby_libs/pav/rangeset.rb +63 -0
  96. data/ruby_libs/pav/search.rb +210 -0
  97. data/ruby_libs/pav/set.rb +130 -0
  98. data/ruby_libs/pav/string/bits.rb +523 -0
  99. data/ruby_libs/pav/string/ext.rb +58 -0
  100. data/ruby_libs/pav/string/observable.rb +155 -0
  101. data/ruby_libs/pav/string/text.rb +79 -0
  102. data/ruby_libs/pav/string/words.rb +42 -0
  103. data/ruby_libs/pav/sub_arr.rb +56 -0
  104. data/ruby_libs/pav/traced_obj.rb +79 -0
  105. data/web/index.html +280 -0
  106. data/web/media/icons/alt_handle.xpm +3832 -0
  107. data/web/media/icons/alt_handle_hover.xpm +3368 -0
  108. data/web/media/icons/alt_handle_pressed.xpm +3828 -0
  109. data/web/media/icons/blob.gif +0 -0
  110. data/web/media/icons/contour.gif +0 -0
  111. data/web/media/icons/contour_carpet.gif +0 -0
  112. data/web/media/icons/curve.gif +0 -0
  113. data/web/media/icons/curve_carpet.gif +0 -0
  114. data/web/media/icons/expand_closed.xpm +1791 -0
  115. data/web/media/icons/expand_closed_hover.xpm +1775 -0
  116. data/web/media/icons/expand_open.xpm +1788 -0
  117. data/web/media/icons/expand_open_hover.xpm +1752 -0
  118. data/web/media/icons/extract_curves/extract_curves-icon-rgb.ppm +14 -0
  119. data/web/media/icons/extract_curves/extract_curves-logo-rgb.gif +0 -0
  120. data/web/media/icons/extract_curves/trace_mark.xpm +38 -0
  121. data/web/media/icons/handle.xpm +213 -0
  122. data/web/media/icons/loop.gif +0 -0
  123. data/web/media/icons/loop_carpet.gif +0 -0
  124. data/web/media/icons/next.xpm +29 -0
  125. data/web/media/icons/next_hover.xpm +315 -0
  126. data/web/media/icons/next_pressed.xpm +144 -0
  127. data/web/media/icons/prev.xpm +29 -0
  128. data/web/media/icons/prev_hover.xpm +315 -0
  129. data/web/media/icons/prev_pressed.xpm +144 -0
  130. data/web/media/icons/shaved-core.gif +0 -0
  131. data/web/media/icons/vnext.xpm +29 -0
  132. data/web/media/icons/vprev.xpm +29 -0
  133. data/web/media/title.jpeg +0 -0
  134. data/web/stylesheets/default.css +20 -0
  135. metadata +192 -0
@@ -0,0 +1,53 @@
1
+ class FloatsInp
2
+ @@float_pat = Regexp.compile(/[+-]?(?:[0-9]+[.]?[0-9]*|[0-9]*[.]?[0-9]+)(?:[eE]?[0-9]*[.]?[0-9]*|)/)
3
+
4
+ attr_reader :io, :rec_buf
5
+
6
+ def initialize(*args)
7
+ @rec_buf = []
8
+ if args[0].kind_of?(IO)
9
+ @io = args[0]
10
+ else
11
+ @io = File.new(*args)
12
+ end
13
+ end
14
+
15
+ def method_missing(id, *args, &block)
16
+ @io.send(id, *args, &block)
17
+ end
18
+
19
+ def get_float
20
+ if @rec_buf.empty? && (ln = self.gets)
21
+ ln.scan(@@float_pat) { |f| @rec_buf << f.to_f }
22
+ end
23
+ @rec_buf.shift
24
+ end
25
+
26
+ def each_float
27
+ while (f = self.get_float)
28
+ yield(f)
29
+ end
30
+ end
31
+
32
+ def get_rec
33
+ if @rec_buf.empty?
34
+ return nil unless (ln = self.gets)
35
+ ln.scan(@@float_pat) { |f| @rec_buf << f.to_f }
36
+ end
37
+ res = @rec_buf
38
+ @rec_buf = []
39
+ res
40
+ end
41
+
42
+ def each_rec
43
+ while (rec = self.get_rec)
44
+ yield(rec)
45
+ end
46
+ end
47
+
48
+ def read_recs
49
+ res = []
50
+ self.each_rec { |rec| res << rec }
51
+ res
52
+ end
53
+ end
@@ -0,0 +1,165 @@
1
+ #require 'generator'
2
+
3
+ class GeneratorCacheArr < Array
4
+ def initialize(gen_spec=nil)
5
+ if !gen_spec
6
+ @gen_func = Proc.new
7
+ elsif gen_spec.kind_of?(Proc) || gen_spec.kind_of?(Method)
8
+ @gen_func = gen_spec
9
+ else
10
+ @gen_func = gen_spec.method("each")
11
+ end
12
+ @end = false
13
+ @next_lm = nil
14
+ super()
15
+ self.rewind
16
+ end
17
+
18
+ def end?
19
+ @end
20
+ end
21
+
22
+ def next?
23
+ !@end
24
+ end
25
+
26
+ def rewind
27
+ callcc { |@ret|
28
+ @gen_func.call { |lm|
29
+ callcc { |@next_lm| @ret.call }
30
+ self << lm
31
+ }
32
+ @end = true
33
+ @next_lm = proc {
34
+ raise EOFError, "no more elements available" }
35
+ @ret.call
36
+ }
37
+ self.clear
38
+ end
39
+
40
+ def next
41
+ callcc { |@ret| @next_lm.call }
42
+ self.last
43
+ end
44
+
45
+ def current
46
+ self.last
47
+ end
48
+
49
+ def index
50
+ self.length - 1
51
+ end
52
+
53
+ def cache_upto(last_i)
54
+ if last_i
55
+ self.length.upto(last_i) {
56
+ return if @end
57
+ self.next
58
+ }
59
+ else
60
+ while !@end
61
+ self.next
62
+ end
63
+ end
64
+ end
65
+
66
+ def [](*args)
67
+ if args.length == 1
68
+ i = args[0]
69
+ if i.kind_of? Range
70
+ if i.first < 0
71
+ last_i = nil
72
+ elsif i.last >= i.first
73
+ last_i = i.last + (i.exclude_end? ? 0:1)
74
+ else
75
+ if i.last + (i.exclude_end? ? 0:-1) < 0
76
+ last_i = nil
77
+ else
78
+ last_i = i.first
79
+ end
80
+ end
81
+ elsif i.kind_of? Array
82
+ last_i = i.max
83
+ elsif i.kind_of? Integer
84
+ if i < 0
85
+ last_i = nil
86
+ else
87
+ last_i = i
88
+ end
89
+ else
90
+ raise ArgumentError,
91
+ "Wrong single argument: #{i.inspect}"
92
+ end
93
+ elsif args.length == 2
94
+ last_i = args[0] + args[1] - 1
95
+ else
96
+ raise ArgumentError,
97
+ "Wrong numbef of arguments: #{args.inspect}"
98
+ end
99
+ self.cache_upto(last_i)
100
+ super(*args)
101
+ end
102
+ end
103
+
104
+ =begin
105
+ class GeneratorCacheArr < Generator
106
+ def initialize(*args, &block)
107
+ @arr = []
108
+ super(*args, &block)
109
+ end
110
+
111
+ def cache_upto(last_i)
112
+ if last_i
113
+ self.index.upto(last_i) {
114
+ return if self.end?
115
+ @arr << self.next
116
+ }
117
+ else
118
+ while !self.end?
119
+ @arr << self.next
120
+ end
121
+ end
122
+ end
123
+
124
+ def [](*args)
125
+ if args.length == 1
126
+ i = args[0]
127
+ if i.kind_of? Range
128
+ if i.first < 0
129
+ last_i = nil
130
+ elsif i.last >= i.first
131
+ last_i = i.last + (i.exclude_end? ? 0:1)
132
+ else
133
+ if i.last + (i.exclude_end? ? 0:-1) < 0
134
+ last_i = nil
135
+ else
136
+ last_i = i.first
137
+ end
138
+ end
139
+ elsif i.kind_of? Array
140
+ last_i = i.max
141
+ elsif i.kind_of? Integer
142
+ if i < 0
143
+ last_i = -i-1
144
+ else
145
+ last_i = i
146
+ end
147
+ else
148
+ raise ArgumentError,
149
+ "Wrong single argument: #{i.inspect}"
150
+ end
151
+ elsif args.length == 2
152
+ last_i = args[0] + args[1] - 1
153
+ else
154
+ raise ArgumentError,
155
+ "Wrong numbef of arguments: #{args.inspect}"
156
+ end
157
+ self.cache_upto(last_i)
158
+ @arr[*args]
159
+ end
160
+
161
+ def []=(*args)
162
+ @arr.[]=(*args)
163
+ end
164
+ end
165
+ =end
@@ -0,0 +1,602 @@
1
+ require 'pav/pix'
2
+ require 'pav/heap'
3
+ require 'pav/collection/std'
4
+
5
+ module PGraph
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_k, :c_reverse
24
+
25
+ def initialize(node, conn_k)
26
+ @node = node
27
+ @conn_k = conn_k
28
+ @c_reverse = nil
29
+ end
30
+
31
+ def ==(link)
32
+ @node.node_eql?(link.node) && @conn_k == link.conn_k
33
+ end
34
+
35
+ def reverse
36
+ return @c_reverse if @c_reverse
37
+ conn = @node.conns[@conn_k]
38
+ exit = conn.exit
39
+ r_conn = conn.reverse(@node)
40
+ exit.conns.each_key_value { |cn_k, cn|
41
+ if cn == r_conn
42
+ return @c_reverse = NodeLink.new(exit, cn_k)
43
+ end
44
+ }
45
+ raise NoReverseLinkError.new(self, @node),
46
+ #"#{self.class.name}.reverse: No rev. link: " +
47
+ "#{self}; conn.: #{node.conns[@conn_k]}; r_conn: #{r_conn}" +
48
+ (exit.conns.length < 50 ? '; '+NodeConn.conns_to_s(
49
+ exit.conns) : '')
50
+ nil
51
+ end
52
+
53
+ def exit
54
+ @node.conns[@conn_k].exit
55
+ end
56
+
57
+ def length
58
+ @node.conns[@conn_k].length
59
+ end
60
+
61
+ def path
62
+ @node.conns[@conn_k].path
63
+ end
64
+
65
+ def conn
66
+ @node.conns[@conn_k]
67
+ end
68
+
69
+ def to_s(how=0)
70
+ "#{@node}-[#{@conn_k}]->" + (how >= 1 ?
71
+ @node.conns[@conn_k].exit.to_s : '')
72
+ end
73
+ end
74
+
75
+ class NodePath < Array
76
+ def ==(path2)
77
+ #$PDbgLog.sig_call(self.name + "#")
78
+ #$PDbgLog.puts_msg "self: #{self}; path2: #{path2}"
79
+ if self.length != path2.length
80
+ # $PDbgLog.sig_return
81
+ return false
82
+ end
83
+ self.each_with_index { |link, i|
84
+ return false if !link = path2.at(i) }
85
+ #$PDbgLog.sig_return
86
+ true
87
+ end
88
+
89
+ def +(path2)
90
+ self.dup.concat(path2)
91
+ end
92
+
93
+ def get_length
94
+ res = 0
95
+ self.each { |link| res += link.length }
96
+ res
97
+ end
98
+
99
+ def entry
100
+ return nil if self.empty?
101
+ self.first.node
102
+ end
103
+
104
+ def exit
105
+ return nil if self.empty?
106
+ self.last.exit
107
+ end
108
+
109
+ alias_method :reverse_links, :reverse
110
+ alias_method :reverse_links!, :reverse!
111
+
112
+ def reverse
113
+ res = []
114
+ self.each_with_index { |link, i|
115
+ res[self.length-i] = link.reverse }
116
+ end
117
+
118
+ def reverse!
119
+ 0.upto(self.length-1) { |i| self[i] = self[i].reverse }
120
+ super
121
+ end
122
+
123
+ def to_s(how=1)
124
+ self.join(' ') << (how > 0 ? self.exit.to_s : '')
125
+ end
126
+
127
+ def each_node
128
+ for link in self
129
+ yield(link.node)
130
+ end
131
+ if (exit = self.exit)
132
+ yield(exit)
133
+ end
134
+ end
135
+ end
136
+
137
+ class NodeConn
138
+ attr_reader :exit, :length
139
+ attr_accessor :path
140
+
141
+ def self.conns_to_s(conns)
142
+ conns.collect {|cn| cn.to_s}.join(', ')
143
+ end
144
+
145
+ def initialize(exit, length)
146
+ @exit = exit
147
+ @length = length
148
+ raise ArgumentError, "Conn.'s exit must be a Node!" unless
149
+ @exit.kind_of?(Node)
150
+ raise ArgumentError, "Conn.'s length must be numeric!" unless
151
+ @length.kind_of?(Numeric)
152
+ end
153
+
154
+ def reverse(conn_0)
155
+ res = NodeConn.new(conn_0, length)
156
+ res.path = path.reverse
157
+ res
158
+ end
159
+
160
+ def max_depth(to_parent_conn_k, visited={})
161
+ return @c_max_depth if @c_max_depth
162
+ @c_max_depth = @length +
163
+ @exit.dir_max_depth(to_parent_conn_k, visited)
164
+ end
165
+
166
+ def to_s(how=0)
167
+ "<-#{@length}->#{@exit}" + (how<1 ? '' : ': ' + self.path.to_s)
168
+ end
169
+
170
+ def eql?(conn)
171
+ @exit.node_eql?(conn.exit) && @length == conn.length &&
172
+ @path == conn.path
173
+ end
174
+
175
+ alias_method :==, :eql?
176
+ end
177
+
178
+ class Node
179
+ attr_reader :data, :conns, :c_rev_conns
180
+ attr_accessor :parent
181
+
182
+ def initialize(data, conns)
183
+ @data = data
184
+ @conns = conns
185
+ @c_rev_conns = conns.class.new
186
+ end
187
+
188
+ def rev_conn_key(conn_k)
189
+ if (tmp = @c_rev_conns[conn_k])
190
+ return tmp
191
+ end
192
+ conn = @conns[conn_k]
193
+ l = conn.exit
194
+ rev_conn = conn.reverse(self)
195
+ l.conns.each_key_value { |cn_k, cn|
196
+ return cn_k if cn == rev_conn }
197
+ raise NoReverseConnError.new(conn, self),
198
+ "#{self.coords_to_s} #{@conns[conn_k].to_s(2)}!"
199
+ nil
200
+ end
201
+
202
+ def to_parent_conn_key(conn_k)
203
+ begin
204
+ self.rev_conn_key(conn_k)
205
+ rescue NoReverseConnError
206
+ if self.node_eql?(@conns[conn_k].exit)
207
+ @c_rev_conns[conn_k] = conn_k
208
+ else
209
+ raise
210
+ end
211
+ end
212
+ end
213
+
214
+ def clear_rev_conns_cache
215
+ @c_rev_conns.clear
216
+ end
217
+
218
+ def delete_conn(conn_k)
219
+ @conns.delete_key(conn_k)
220
+ @c_rev_conns.delete_key(conn_k)
221
+ end
222
+
223
+ def conns_to_s
224
+ NodeConn.conns_to_s(@conns)
225
+ end
226
+
227
+ def eql?(node)
228
+ @data.eql?(node.data)
229
+ end
230
+
231
+ alias_method :node_eql?, :eql?
232
+
233
+ def hash
234
+ @data.hash
235
+ end
236
+
237
+ def each_link
238
+ @conns.each_key { |conn_k| yield(NodeLink.new(self, conn_k)) }
239
+ end
240
+
241
+ def get_min_lp_n_len(max_len=1.0/0.0)
242
+ #$PDbgLog.sig_call(self)
243
+ #$PDbgLog.print_msg self.coords_to_s + ", max_len=#{max_len}: "
244
+ p1, p2, len = *PSearch.first_norep_loop(self, max_len, max_len,
245
+ proc { |p| p.data }) { |node, lev|
246
+ res = []
247
+ node.conns.each_key_value { |cn_k, cn|
248
+ res << [cn.exit,NodeLink.new(node,cn_k),lev+cn.length] }
249
+ res
250
+ }
251
+ unless p1
252
+ #$PDbgLog.sig_return
253
+ return [nil, nil]
254
+ end
255
+ #$PDbgLog.puts_msg 'p1: ' + p1.collect { |link|
256
+ # link ? link.to_s(1) : link.inspect }.join(' ')
257
+ #$PDbgLog.puts_msg 'p2: ' + p2.collect { |link|
258
+ # link ? link.to_s(1) : link.inspect }.join(' ')
259
+ lp = NodePath.new
260
+ p2.reverse_each { |link| lp << link }
261
+ p1.each { |link| lp << link.reverse }
262
+ #$PDbgLog.sig_return(lp)
263
+ [lp, len]
264
+ end
265
+
266
+ def dup_with_map(map)
267
+ if (tmp = map[self])
268
+ return tmp
269
+ end
270
+ res = map[self] = Node.new(@data, conns=@conns.class.new)
271
+ @conns.each { |conn|
272
+ new_conn = NodeConn.new(conn.exit.dup_with_map(map),
273
+ conn.length)
274
+ new_conn.path = conn.path
275
+ conns << new_conn
276
+ }
277
+ res
278
+ end
279
+
280
+ def dup_graph
281
+ self.dup_with_map({})
282
+ end
283
+
284
+ def conn_max_depth(conn_k)
285
+ begin
286
+ rev_conn_k = self.rev_conn_key(conn_k)
287
+ rescue NoReversePathwayError
288
+ rev_conn_k = nil
289
+ end
290
+ @conns[conn_k].max_depth(rev_conn_k)
291
+ end
292
+
293
+ def dir_max_depth(to_parent_conn_k, visited)
294
+ #$PDbgLog.sig_call(self)
295
+ max_depth = 0
296
+ visited[self] = true
297
+ @conns.each_key_value { |conn_k, conn|
298
+ next if to_parent_conn_k == conn_k
299
+ if visited.include?(conn.exit)
300
+ max_depth = 1.0/0.0
301
+ break
302
+ end
303
+ tmp = conn.max_depth(self.rev_conn_key(conn_k), visited)
304
+ max_depth = tmp if tmp > max_depth
305
+ }
306
+ #$PDbgLog.sig_return
307
+ max_depth
308
+ end
309
+
310
+ def graph_each_conn_k(visited={}, &block)
311
+ if visited.include?(self)
312
+ vis_conns = visited[self]
313
+ else
314
+ vis_conns = visited[self] = @conns.class.new
315
+ end
316
+ @conns.each_key_value { |conn_k, conn|
317
+ unless vis_conns[conn_k]
318
+ yield(self, conn_k)
319
+ vis_conns[conn_k] = true
320
+ begin
321
+ visited[conn.exit] = conn.exit.conns.class.new unless
322
+ visited.include?(conn.exit)
323
+ visited[conn.exit][self.rev_conn_key(conn_k)] = true
324
+ rescue NoReversePathwayError
325
+ end
326
+ conn.exit.graph_each_conn_k(visited, &block)
327
+ end
328
+ }
329
+ end
330
+
331
+ def graph_each_node(visited={}, &block)
332
+ return if visited.include?(self)
333
+ visited[self] = true
334
+ yield(self)
335
+ @conns.each {|conn| conn.exit.graph_each_node(visited, &block) }
336
+ end
337
+
338
+ def to_s(how=0)
339
+ res = @data.to_s
340
+ return res if how < 1
341
+ res.concat('+conns: ')
342
+ @conns.each_key_value { |conn_k, conn|
343
+ res.concat("[#{conn_k}]#{conn.to_s(how-1)}; ")
344
+ }
345
+ res[-2,2] = ''
346
+ res
347
+ end
348
+
349
+ def graph_to_s
350
+ res = ''
351
+ self.graph_each_conn_k { |node, conn_k|
352
+ res.concat(node.to_s + ": [#{conn_k}]#{node.conns[
353
+ conn_k].to_s(2)}\n")
354
+ }
355
+ res
356
+ end
357
+ end
358
+
359
+ class NodeCalcPCachePathIter
360
+ attr_accessor :path_cache, :node
361
+
362
+ def initialize(path_cache=nil, node=nil)
363
+ @path_cache = path_cache
364
+ @node = node
365
+ end
366
+
367
+ def pop
368
+ to_link = path_cache[@node][1]
369
+ @node = to_link ? to_link.node : nil
370
+ to_link
371
+ end
372
+ end
373
+
374
+ class NodeCalc
375
+ attr_reader :node, :c_paths
376
+ attr_accessor :link_filter
377
+
378
+ def initialize(node)
379
+ @node = node
380
+ @c_paths = {}
381
+ @link_filter = nil
382
+ end
383
+
384
+ def find_shortest_path_to_node(dest, max_lev=1.0/0.0,
385
+ path_cache=@c_paths)
386
+ #$PDbgLog.sig_call(self)
387
+ if max_lev < 0
388
+ #$PDbgLog.sig_return("max_lev < 0: nil")
389
+ return nil
390
+ end
391
+ path_cache = {} unless path_cache
392
+ if @link_filter
393
+ #$PDbgLog.sig_return
394
+ return self.find_shortest_path_to_node_with_link_filter(
395
+ dest, max_lev, path_cache)
396
+ end
397
+ path_cache[@node] = [0, nil] unless path_cache.include?(@node)&&
398
+ path_cache[@node][0] <= 0 && path_cache[@node][1] == nil
399
+ tail = PMinHeap.new { |a,b| a[1] <=> b[1] }
400
+ path_cache.each_pair { |node, frm| tail.push([node, frm[0]]) }
401
+ while !tail.empty?
402
+ node, lev = *tail.pop
403
+ next if path_cache.include?(node) &&
404
+ path_cache[node][0] < lev
405
+ if path_cache.include?(dest)
406
+ res = NodePath.new; node = dest
407
+ to_link = path_cache[node][1]
408
+ while to_link
409
+ res << to_link
410
+ to_link = path_cache[to_link.node][1]
411
+ end
412
+ res.reverse_links!
413
+ #$PDbgLog.sig_return(res.inspect)
414
+ return res
415
+ end
416
+ node.conns.each_key_value { |conn_k,conn| l = conn.exit
417
+ if (l_lev = lev+conn.length) <= max_lev &&
418
+ (!path_cache.include?(l) || path_cache[l][0] > l_lev)
419
+ tail.push([l, l_lev])
420
+ path_cache[l]=[l_lev,NodeLink.new(node,conn_k)]
421
+ end
422
+ }
423
+ end
424
+ #$PDbgLog.sig_return("nil")
425
+ nil
426
+ end
427
+
428
+ def find_shortest_path_to_node_with_link_filter(dest, max_lev,
429
+ path_cache)
430
+ #$PDbgLog.sig_call(self)
431
+ path_cache[@node] = [0, nil] unless path_cache.include?(@node)&&
432
+ path_cache[@node][0] <= 0 && path_cache[@node][1] == nil
433
+ tail = PMinHeap.new { |a,b| a[1] <=> b[1] }
434
+ path_cache.each_pair { |node, frm| tail.push([node, frm[0]]) }
435
+ #$PDbgLog.print_msg "node#{@node.coords_to_s}, dest#{dest.
436
+ # coords_to_s}, max_lev=#{max_lev}: "
437
+ while !tail.empty?
438
+ node, lev = *tail.pop
439
+ # $PDbgLog.print_msg "node#{node.coords_to_s},lev=#{lev} "
440
+ next if path_cache.include?(node) &&
441
+ path_cache[node][0] < lev
442
+ if path_cache.include?(dest)
443
+ res = NodePath.new; node = dest
444
+ to_link = path_cache[node][1]
445
+ while to_link
446
+ res << to_link
447
+ to_link = path_cache[to_link.node][1]
448
+ end
449
+ res.reverse_links!
450
+ #$PDbgLog.sig_return('found ' + res.to_s + '.')
451
+ return res
452
+ end
453
+ node.conns.each_key_value { |conn_k,conn| l = conn.exit
454
+ #$PDbgLog.print_msg "conn #{conn_k}: #{conn} "
455
+ if (l_lev = lev+conn.length) <= max_lev &&
456
+ (!path_cache.include?(l) || path_cache[l][0]>l_lev) &&
457
+ @link_filter.call(link=NodeLink.new(node,conn_k))
458
+ tail.push([l, l_lev])
459
+ path_cache[l]=[l_lev, link]
460
+ end
461
+ }
462
+ end
463
+ #$PDbgLog.sig_return("no path found.")
464
+ nil
465
+ end
466
+
467
+ def self.path_cache_to_s(path_cache)
468
+ "{#{path_cache.keys.to_a.sort.collect{|k| k.to_s + "=>[#{
469
+ path_cache[k][0]}, " + (path_cache[k][1] ?
470
+ path_cache[k][1].to_s : 'nil') + "]"}.join(", ")}}"
471
+ end
472
+
473
+ def self.path_cache_get_path_to_self(node, path_cache)
474
+ to_link = path_cache[node][1]
475
+ res = NodePath.new
476
+ while !to_link.node.node_eql?(node)
477
+ res << to_link
478
+ to_link = path_cache[to_link.node]
479
+ end
480
+ res << to_link
481
+ res.reverse_links!
482
+ end
483
+
484
+ def self.path_cache_get_path(node, path_cache)
485
+ #$PDbgLog.sig_call(self)
486
+ #$PDbgLog.print_msg "node#{node}, path_cache: #{self.
487
+ # path_cache_to_s(path_cache)}: "
488
+ to_link = path_cache[node][1]
489
+ res = NodePath.new
490
+ while to_link
491
+ res << to_link
492
+ to_link = path_cache[to_link.node][1]
493
+ end
494
+ res.reverse_links!
495
+ #$PDbgLog.sig_return(res.to_s(1))
496
+ res
497
+ end
498
+
499
+ def find_first_path_to(dest, max_lev=1.0/0.0, path_cache=nil)
500
+ if max_lev < 0
501
+ return nil
502
+ end
503
+ if @link_filter
504
+ return self.find_first_path_to_with_link_filter(dest,
505
+ max_lev, path_cache)
506
+ end
507
+ if dest.kind_of?(Proc)
508
+ dest_proc = dest
509
+ else
510
+ dest_proc = proc {|node,lev| dest.node_eql?(node)}
511
+ end
512
+ tail = PMinHeap.new { |frm1,frm2| frm1[1] <=> frm2[1] }
513
+ unless path_cache
514
+ path_cache = @c_paths
515
+ unless dest.kind_of?(Proc)
516
+ return NodeCalc.path_cache_get_path(dest,
517
+ path_cache) if path_cache.include?(dest)
518
+ end
519
+ path_cache.each_pair { |node, frm|
520
+ tail.push([node, frm[0]]) }
521
+ end
522
+ path_cache[@node] = [0, nil]
523
+ tail.push([@node, 0])
524
+ while !tail.empty?
525
+ node, lev = *tail.pop
526
+ next if path_cache.include?(node) &&
527
+ path_cache[node][0] < lev
528
+ if dest_proc.call(node, lev)
529
+ res = NodeCalc.path_cache_get_path(node,
530
+ path_cache)
531
+ return res
532
+ end
533
+ node.conns.each_key_value { |conn_k,conn| l = conn.exit
534
+ if (l_lev = lev + conn.length) <= max_lev &&
535
+ (!path_cache.include?(l) || path_cache[l][0] > l_lev)
536
+ tail.push([l, l_lev])
537
+ path_cache[l]=[l_lev,NodeLink.new(node,conn_k)]
538
+ end
539
+ }
540
+ end
541
+ nil
542
+ end
543
+
544
+ def find_first_path_to_with_link_filter(dest, max_lev, path_cache=nil)
545
+ #$PDbgLog.sig_call(self)
546
+ #$PDbgLog.print_msg "dest:#{dest}, max_lev=#{max_lev}"
547
+ if dest.kind_of?(Proc)
548
+ dest_proc = dest
549
+ else
550
+ dest_proc = proc {|node,lev| dest.node_eql?(node)}
551
+ end
552
+ tail = PMinHeap.new { |frm1,frm2| frm1[1] <=> frm2[1] }
553
+ unless path_cache
554
+ path_cache = @c_paths
555
+ if !dest.kind_of?(Proc) && path_cache.include?(dest)
556
+ #$PDbgLog.sig_return(': cached.')
557
+ return NodeCalc.path_cache_get_path(dest,
558
+ path_cache)
559
+ end
560
+ path_cache.each_pair { |node, frm|
561
+ tail.push([node, frm[0]]) }
562
+ end
563
+ path_cache[@node] = [0, nil]
564
+ tail.push([@node, 0])
565
+ while !tail.empty?
566
+ node, lev = *tail.pop
567
+ next if path_cache.include?(node) &&
568
+ path_cache[node][0] < lev
569
+ #$PDbgLog.print_msg "node#{node},lev=#{lev} "
570
+ if dest_proc.call(node, lev)
571
+ res = NodeCalc.path_cache_get_path(node,
572
+ path_cache)
573
+ #$PDbgLog.sig_return('Done.')
574
+ return res
575
+ end
576
+ node.conns.each_key_value { |conn_k,conn| l = conn.exit
577
+ if (l_lev = lev + conn.length) <= max_lev &&
578
+ (!path_cache.include?(l) || path_cache[l][0]>l_lev) &&
579
+ @link_filter.call(link=NodeLink.new(node,conn_k))
580
+ tail.push([l, l_lev])
581
+ path_cache[l] = [l_lev, link]
582
+ end
583
+ }
584
+ end
585
+ #$PDbgLog.sig_return(': nil')
586
+ nil
587
+ end
588
+
589
+ def kill_path_cache!
590
+ @c_paths.clear
591
+ end
592
+
593
+ def path_cache_each_path
594
+ iter = NodeCalcPCachePathIter.new(@c_paths)
595
+ @c_paths.each_key { |node|
596
+ iter.node = node
597
+ yield(iter)
598
+ }
599
+ end
600
+ end
601
+
602
+ end