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,865 @@
1
+ require 'set'
2
+ require 'pav/graph/node'
3
+
4
+ module PGraph
5
+
6
+ class GrpNodeConnProxyToExterior < NodeConn
7
+ def reverse(conn_0)
8
+ link = self.path.last
9
+ link.conn.reverse(link.node)
10
+ end
11
+ end
12
+
13
+ class NodeGrp < Set
14
+ def initialize(*args)
15
+ super(*args)
16
+ @cache_get_node_paths_to_exterior = {}
17
+ @cache_get_node_shortest_paths_to_exterior = {}
18
+ @cache_get_node_paths_to_entries = {}
19
+ @link_filter = proc { |link| self.include?(link.exit) }
20
+ end
21
+
22
+ alias_method :includes_node?, :include?
23
+ alias_method :nodes_to_a, :to_a
24
+ alias_method :node_cnt, :length
25
+ alias_method :each_node, :each
26
+
27
+ cache_get_lm! :get_node_paths_to_exterior,
28
+ :get_node_shortest_paths_to_exterior, :get_node_paths_to_entries
29
+
30
+ def get_all_links_to(node)
31
+ res = []
32
+ self.each { |m| m.conns.each_key_value { |cn_k, cn|
33
+ res << NodeLink.new(m,cn_k) if node.node_eql?(cn.exit)}}
34
+ res
35
+ end
36
+
37
+ def get_entries_grp
38
+ res = NodeGrp.new
39
+ self.each { |m|
40
+ if m.conns.detect { |conn| !self.include?(conn.exit) }
41
+ res << m
42
+ end
43
+ }
44
+ res
45
+ end
46
+
47
+ def get_terminals
48
+ known = {}
49
+ self.each { |m| known[m] = true }
50
+ terminals = []
51
+ self.each { |m| m.conns.each { |cn|
52
+ unless known.include?(cn.exit)
53
+ terminals << cn.exit
54
+ known[cn.exit] = true
55
+ end
56
+ }}
57
+ terminals
58
+ end
59
+
60
+ def get_vicinity_grp(max_distc)
61
+ res = NodeGrp.new(self)
62
+ tail = []
63
+ self.each { |m| tail.push([m, 0]) }
64
+ while !tail.empty?
65
+ nd, lev = *tail.pop
66
+ nd.conns.each { |cn|
67
+ if (n_lev = lev + cn.length) <= max_distc &&
68
+ !res.include?(cn.exit)
69
+ res << cn.exit
70
+ tail.push([cn.exit, n_lev])
71
+ end
72
+ }
73
+ end
74
+ res
75
+ end
76
+
77
+ def get_vicinity_grp_in_set(max_distc, incl_set)
78
+ res = NodeGrp.new(self)
79
+ tail = []
80
+ self.each { |m| tail.push([m, 0]) if incl_set.include?(m) }
81
+ while !tail.empty?
82
+ nd, lev = *tail.pop
83
+ nd.conns.each { |cn|
84
+ if (n_lev = lev + cn.length) <= max_distc &&
85
+ !res.include?(cn.exit) && incl_set.include?(cn.exit)
86
+ res << cn.exit
87
+ tail.push([cn.exit, n_lev])
88
+ end
89
+ }
90
+ end
91
+ res
92
+ end
93
+
94
+ cache_get! :get_entries_grp, :get_terminals
95
+
96
+ def get_node_paths_to_exterior(node, node_calc=nil)
97
+ node_calc = NodeCalc.new(node) unless node_calc
98
+ node_calc.link_filter = @link_filter
99
+ paths = []
100
+ self.each { |m|
101
+ path = node_calc.find_shortest_path_to_node(m)
102
+ m.conns.each_key_value { |conn_k, conn|
103
+ next if self.include?(conn.exit)
104
+ paths << path + [NodeLink.new(m, conn_k)]
105
+ }
106
+ }
107
+ paths
108
+ end
109
+
110
+ def get_node_shortest_paths_to_exterior(node, node_calc=nil)
111
+ #$PDbgLog.sig_call(self)
112
+ node_calc = NodeCalc.new(node) unless node_calc
113
+ node_calc.link_filter = @link_filter
114
+ paths = {}
115
+ self.each { |m|
116
+ path = node_calc.find_shortest_path_to_node(m)
117
+ path_len = path.get_length
118
+ m.conns.each_key_value { |conn_k, conn|
119
+ next if self.include?(conn.exit)
120
+ len = path_len + conn.length
121
+ next if paths.include?(conn.exit) &&
122
+ paths[conn.exit][1] <= len
123
+ paths[conn.exit] =
124
+ [path+[NodeLink.new(m,conn_k)], len]
125
+ }
126
+ }
127
+ res = []
128
+ paths.each_value { |p_spec| res << p_spec[0] }
129
+ #$PDbgLog.sig_return(res.inspect)
130
+ res
131
+ end
132
+
133
+ def get_node_paths_to_entries(node, node_calc=nil)
134
+ #$PDbgLog.sig_call(self)
135
+ node_calc = NodeCalc.new(node) unless node_calc
136
+ node_calc.link_filter = @link_filter
137
+ paths = []
138
+ self.each { |m| next if m.node_eql?(node)
139
+ if m.conns.detect { |conn| !self.include?(conn.exit) }
140
+ #$PDbgLog.print_msg "Entry #{m.coords_to_s}: "
141
+ paths << node_calc.find_shortest_path_to_node(m)
142
+ #$PDbgLog.puts_msg paths.last.to_s + '.'
143
+ end
144
+ }
145
+ #$PDbgLog.sig_return
146
+ paths
147
+ end
148
+
149
+ def self.get_node_vicinity_grp(node, max_distc)
150
+ res = NodeGrp.new
151
+ res << node
152
+ tail = [node, 0]
153
+ while !tail.empty?
154
+ nd, lev = *tail.pop
155
+ nd.conns.each { |cn|
156
+ if (n_lev = lev + cn.length) <= max_distc &&
157
+ !res.include?(cn.exit)
158
+ res << cn.exit
159
+ tail.push([cn.exit, n_lev])
160
+ end
161
+ }
162
+ end
163
+ res
164
+ end
165
+
166
+ def get_a_longest_path
167
+ #$PDbgLog.sig_call(self)
168
+ max_path = nil
169
+ max_path_len = -1
170
+ self.each { |m_0|
171
+ node_calc = NodeCalc.new(m_0)
172
+ node_calc.link_filter = @link_filter
173
+ self.each { |m_end| next if m_end.a_eql?(m_0)
174
+ # $PDbgLog.print_msg "m_0#{m_0.coords_to_s}, m_end#{m_end.
175
+ # coords_to_s}: "
176
+ path = node_calc.find_shortest_path_to_node(m_end)
177
+ #$PDbgLog.puts_msg path.to_s
178
+ if (len = path.get_length) > max_path_len
179
+ max_path = path; max_path_len = len
180
+ end
181
+ }
182
+ }
183
+ #$PDbgLog.sig_return
184
+ max_path
185
+ end
186
+
187
+ cache_get! :get_a_longest_path
188
+
189
+ def get_node_islands(dyke_set)
190
+ assigned = Set.new(dyke_set)
191
+ islands = []
192
+ dyke_set.each { |m| m.conns.each { |conn|
193
+ if self.include?(conn.exit) &&
194
+ !assigned.include?(conn.exit)
195
+ island = NodeGrp.new; island << conn.exit
196
+ tail = [conn.exit]
197
+ while !tail.empty?
198
+ node = tail.pop
199
+ node.conns.each { |cn|
200
+ if self.include?(cn.exit) &&
201
+ !assigned.include?(cn.exit)
202
+ island << cn.exit
203
+ assigned << cn.exit
204
+ tail.push(cn.exit)
205
+ end
206
+ }
207
+ end
208
+ end
209
+ } }
210
+ islands
211
+ end
212
+
213
+ def find_first_path_to(dest, max_distc=1.0/0.0)
214
+ return nil if max_distc < 0
215
+ if dest.kind_of?(Proc)
216
+ dest_proc = dest
217
+ else
218
+ dest_proc = proc { |nd| dest.node_eql?(nd) }
219
+ end
220
+ c_paths = {}
221
+ tail = PMinHeap.new { |a,b| a[1] <=> b[1] }
222
+ self.each { |m| c_paths[m] = [0, nil]; tail.push([m, 0]) }
223
+ while !tail.empty?
224
+ node, lev = *tail.pop
225
+ if dest_proc.call(node)
226
+ return NodeCalc.path_cache_get_path(node, c_paths)
227
+ end
228
+ next if c_paths.include?(node) && c_paths[node][0] <=lev
229
+ node.conns.each_key_value { |conn_k, conn|
230
+ if (c_lev = lev + conn.length) <= max_distc &&
231
+ !c_paths.include?(conn.exit) ||
232
+ c_paths[conn.exit][0] > c_lev
233
+ c_paths[conn.exit] = [c_lev, NodeLink.
234
+ new(node, conn_k)]
235
+ tail.push([conn.exit, c_lev])
236
+ end
237
+ }
238
+ end
239
+ nil
240
+ end
241
+
242
+ def get_islands_min_span_grp(islands)
243
+ return nil if islands.empty?
244
+ node2grp = {}
245
+ islands.each { |isl| isl.each { |m| node2grp[m] = isl } }
246
+ res = NodeGrp.new(islands.first)
247
+ tail = PMinHeap.new { |a,b| a[1] <=> b[1] }
248
+ c_paths = {}
249
+ res.each { |m| tail.push([m, 0]); c_paths[m] = [0, nil] }
250
+ grps_left = islands.length - 1
251
+ while grps_left > 0
252
+ lev, node = *tail.pop
253
+ node.conns.each_key_value { |conn_k, conn|
254
+ c_lev = lev + conn.length
255
+ if !c_paths.include?(conn.exit) ||
256
+ c_paths[conn.exit][0] > c_lev
257
+ if (grp = node2grp[conn.exit]) &&
258
+ grp.object_id != res.object_id
259
+ grp.each{|m| res << m; node2grp[m]=res
260
+ c_paths[m] = [0, nil]
261
+ tail.push([m, 0])
262
+ }
263
+ grps_left -= 1
264
+ to_link = c_paths[node][1]
265
+ while to_link
266
+ res << to_link.node
267
+ node2grp[to_link.node] = res
268
+ to_link=c_paths[to_link.node][1]
269
+ end
270
+ end
271
+ else
272
+ c_paths[conn.exit] =
273
+ [c_lev, NodeLink.new(node, conn_k)]
274
+ tail.push([c_lev, conn.exit])
275
+ end
276
+ }
277
+ end
278
+ res
279
+ end
280
+
281
+ def get_islands_min_span_paths(islands)
282
+ res = []
283
+ return res if islands.empty?
284
+ node2grp = {}
285
+ islands.each { |isl| isl.each { |m| node2grp[m] = isl } }
286
+ grp0 = NodeGrp.new(islands.first)
287
+ tail = PMinHeap.new { |a,b| a[1] <=> b[1] }
288
+ c_paths = {}
289
+ grp0.each { |m| tail.push([m, 0]); c_paths[m] = [0, nil] }
290
+ grps_left = islands.length - 1
291
+ while grps_left > 0
292
+ lev, node = *tail.pop
293
+ node.conns.each_key_value { |conn_k, conn|
294
+ next unless self.include?(conn.exit)
295
+ c_lev = lev + conn.length
296
+ if !c_paths.include?(conn.exit) ||
297
+ c_paths[conn.exit][0] > c_lev
298
+ if (grp = node2grp[conn.exit]) &&
299
+ grp.object_id != res.object_id
300
+ grp.each{|m| node2grp[m]=grp0
301
+ c_paths[m] = [0, nil]
302
+ tail.push([m, 0])
303
+ }
304
+ grps_left -= 1
305
+ path = NodePath.new
306
+ to_link = c_paths[node][1]
307
+ while to_link
308
+ path << to_link
309
+ node2grp[to_link.node] = grp0
310
+ to_link=c_paths[to_link.node][1]
311
+ end
312
+ path.reverse_links!
313
+ res << path
314
+ end
315
+ else
316
+ c_paths[conn.exit] =
317
+ [c_lev, NodeLink.new(node, conn_k)]
318
+ tail.push([c_lev, conn.exit])
319
+ end
320
+ }
321
+ end
322
+ res
323
+ end
324
+
325
+ def to_s
326
+ arr = self.to_a; arr.sort!
327
+ '{' + arr.join(', ') + '}'
328
+ end
329
+ end
330
+
331
+ class LinkGrpAsNodeSet
332
+ attr_reader :link_grp
333
+
334
+ def initialize(link_grp)
335
+ @link_grp = link_grp
336
+ end
337
+
338
+ def include?(node)
339
+ @link_grp.includes_node?(node)
340
+ end
341
+ end
342
+
343
+ class LinkGrp
344
+ def initialize
345
+ super()
346
+ @cache_get_node_paths_to_exterior = {}
347
+ @cache_get_node_paths_to_external_nodes = {}
348
+ @cache_get_node_shortest_paths_to_exterior = {}
349
+ @cache_get_node_shortest_paths_to_external_nodes = {}
350
+ @cache_get_node_paths_to_border = {}
351
+ @cache_get_node_paths_to_entries = {}
352
+ @node2links = {}
353
+ @link_filter = self.method('include?').to_proc
354
+ end
355
+
356
+ def add(link)
357
+ unless (links = @node2links[link.node])
358
+ links = @node2links[link.node]=link.node.conns.class.new
359
+ end
360
+ links[link.conn_k] = link
361
+ end
362
+
363
+ def <<(link)
364
+ unless (links = @node2links[link.node])
365
+ links = @node2links[link.node]=link.node.conns.class.new
366
+ end
367
+ links[link.conn_k] = link
368
+ self
369
+ end
370
+
371
+ def delete(link)
372
+ if (links = @node2links[link.node])
373
+ links[link.conn_k] = nil
374
+ end
375
+ end
376
+
377
+ def node_delete_conn(node, conn_k)
378
+ node.delete_conn(conn_k)
379
+ if (links = @node2links[node]) && links[conn_k]
380
+ links.delete_key(conn_k)
381
+ else
382
+ warn("#{self.class.name}.node_delete_conn: Link not " \
383
+ "in group: node: #{node}, conn_k: #{conn_k}")
384
+ end
385
+ end
386
+
387
+ def include?(link)
388
+ (links = @node2links[link.node]) && links[link.conn_k]
389
+ end
390
+
391
+ alias_method :member?, :include?
392
+
393
+ def includes_node?(node)
394
+ @node2links.include?(node)
395
+ end
396
+
397
+ alias_method :include_node?, :includes_node?
398
+
399
+ def each
400
+ @node2links.each_pair { |node, links|
401
+ links.each { |link| yield(link) if link } }
402
+ end
403
+
404
+ def each_node(&block)
405
+ @node2links.each_key(&block)
406
+ end
407
+
408
+ def to_a
409
+ res = []
410
+ self.each { |link| res << link }
411
+ res
412
+ end
413
+
414
+ def nodes_to_a
415
+ @node2links.keys
416
+ end
417
+
418
+ def nodes_to_node_grp
419
+ res = NodeGrp.new
420
+ self.each_node { |node| res << node }
421
+ res
422
+ end
423
+
424
+ def as_node_set
425
+ LinkGrpAsNodeSet.new(self)
426
+ end
427
+
428
+ def to_s
429
+ nodes = @node2links.keys; nodes.sort!
430
+ res = '{'
431
+ nodes.each { |node| res << node.to_s << ':'
432
+ @node2links[node].each_key_value { |link_k,link|
433
+ res << " #{link_k}" if link }
434
+ res << '; '
435
+ }
436
+ res[-2] ? res[-2,2] = '}' : res << '}'
437
+ res
438
+ end
439
+
440
+ def node_cnt
441
+ @node2links.length
442
+ end
443
+
444
+ def add_undir_path!(path)
445
+ path.each { |link| self << link
446
+ begin
447
+ self << link.reverse
448
+ rescue NoReverseLinkError
449
+ end
450
+ }
451
+ end
452
+
453
+ alias_method :add_undir_path, :add_undir_path!
454
+
455
+ cache_get_lm! :get_node_paths_to_exterior,
456
+ :get_node_paths_to_external_nodes,
457
+ :get_node_shortest_paths_to_exterior,
458
+ :get_node_shortest_paths_to_external_nodes,
459
+ :get_node_paths_to_border, :get_node_paths_to_entries
460
+
461
+ def get_all_links_to(node)
462
+ res = []
463
+ self.each { |m| res << m if node.node_eql?(node) }
464
+ res
465
+ end
466
+
467
+ def get_entries_grp
468
+ res = NodeGrp.new
469
+ @node2links.each_pair { |node, links|
470
+ node.conns.each_key { |conn_k|
471
+ unless links[conn_k]
472
+ res << node; break
473
+ end
474
+ }
475
+ }
476
+ res
477
+ end
478
+
479
+ def get_border_grp
480
+ res = NodeGrp.new
481
+ self.each_node { |node|
482
+ res << node if node.conns.detect { |conn|
483
+ !self.includes_node?(conn.exit) }
484
+ }
485
+ res
486
+ end
487
+
488
+ def get_terminals
489
+ known = {}
490
+ self.each_node { |node| known[node] = true }
491
+ terminals = []
492
+ self.each_node { |node| node.conns.each { |cn|
493
+ unless known.include?(cn.exit)
494
+ terminals << cn.exit
495
+ known[cn.exit] = true
496
+ end
497
+ }}
498
+ terminals
499
+ end
500
+
501
+ def get_vicinity_grp(max_distc)
502
+ res = NodeGrp.new(self)
503
+ tail = []
504
+ self.each_node { |node| tail.push([node, 0]) }
505
+ while !tail.empty?
506
+ nd, lev = *tail.pop
507
+ nd.conns.each { |cn|
508
+ if (n_lev = lev + cn.length) <= max_distc &&
509
+ !res.include?(cn.exit)
510
+ res << cn.exit
511
+ tail.push([cn.exit, n_lev])
512
+ end
513
+ }
514
+ end
515
+ res
516
+ end
517
+
518
+ cache_get! :get_entries_grp, :get_border_grp, :get_terminals
519
+
520
+ def get_node_paths_to_external_nodes(node, node_calc=nil)
521
+ node_calc = NodeCalc.new(node) unless node_calc
522
+ node_calc.link_filter = @link_filter
523
+ paths = []
524
+ self.each_node { |node|
525
+ path = node_calc.find_shortest_path_to_node(node)
526
+ node.conns.each_key_value { |conn_k, conn|
527
+ next if self.includes_node?(conn.exit)
528
+ paths << path + [NodeLink.new(node, conn_k)]
529
+ }
530
+ }
531
+ paths
532
+ end
533
+
534
+ def get_node_paths_to_exterior(node, node_calc=nil)
535
+ node_calc = NodeCalc.new(node) unless node_calc
536
+ node_calc.link_filter = @link_filter
537
+ paths = []
538
+ self.each_node { |node|
539
+ path = node_calc.find_shortest_path_to_node(node)
540
+ links = @node2links[node]
541
+ node.conns.each_key_value { |conn_k, conn|
542
+ next if links[conn_k]
543
+ paths << path + [NodeLink.new(node, conn_k)]
544
+ }
545
+ }
546
+ paths
547
+ end
548
+
549
+ def get_node_shortest_paths_to_external_nodes(node, node_calc=nil)
550
+ #$PDbgLog.sig_call(self)
551
+ node_calc = NodeCalc.new(node) unless node_calc
552
+ node_calc.link_filter = @link_filter
553
+ paths = {}
554
+ self.each_node { |node|
555
+ path = node_calc.find_shortest_path_to_node(node)
556
+ path_len = path.get_length
557
+ node.conns.each_key_value { |conn_k, conn|
558
+ next if self.includes_node?(conn.exit)
559
+ len = path_len + conn.length
560
+ next if paths.include?(conn.exit) &&
561
+ paths[conn.exit][1] <= len
562
+ paths[conn.exit] =
563
+ [path+[NodeLink.new(node,conn_k)], len]
564
+ }
565
+ }
566
+ res = []
567
+ paths.each_value { |p_spec| res << p_spec[0] }
568
+ #$PDbgLog.sig_return(res.inspect)
569
+ res
570
+ end
571
+
572
+ def get_node_shortest_paths_to_exterior(node, node_calc=nil)
573
+ #$PDbgLog.sig_call(self)
574
+ node_calc = NodeCalc.new(node) unless node_calc
575
+ node_calc.link_filter = @link_filter
576
+ paths = {}
577
+ self.each_node { |node|
578
+ path = node_calc.find_shortest_path_to_node(node)
579
+ path_len = path.get_length
580
+ links = @node2links[node]
581
+ node.conns.each_key_value { |conn_k, conn|
582
+ next if links[conn_k]
583
+ len = path_len + conn.length
584
+ link = NodeLink.new(node, conn_k)
585
+ next if paths.include?(link) &&
586
+ paths[link][1] <= len
587
+ paths[link] = [path + [link], len]
588
+ }
589
+ }
590
+ res = []
591
+ paths.each_value { |p_spec| res << p_spec[0] }
592
+ #$PDbgLog.sig_return(res.inspect)
593
+ res
594
+ end
595
+
596
+ def get_node_paths_to_border(node, node_calc=nil)
597
+ node_calc = NodeCalc.new(node) unless node_calc
598
+ node_calc.link_filter = @link_filter
599
+ paths = []
600
+ self.each_node { |nd| next if nd.node_eql?(node)
601
+ if nd.conns.detect { |conn| !self.includes_node?(conn.exit) }
602
+ path = node_calc.find_shortest_path_to_node(nd)
603
+ paths << path
604
+ end
605
+ }
606
+ paths
607
+ end
608
+
609
+ def get_node_paths_to_entries(node, node_calc=nil)
610
+ node_calc = NodeCalc.new(node) unless node_calc
611
+ node_calc.link_filter = @link_filter
612
+ paths = []
613
+ self.each_node { |nd| next if nd.node_eql?(node)
614
+ links = @node2links[nd]
615
+ nd.conns.each_key { |conn_k|
616
+ unless links[conn_k]
617
+ path = node_calc.find_shortest_path_to_node(nd)
618
+ paths << path
619
+ break
620
+ end
621
+ }
622
+ }
623
+ paths
624
+ end
625
+
626
+ def get_a_longest_path
627
+ #$PDbgLog.sig_call(self)
628
+ max_path = nil
629
+ max_path_len = 0
630
+ node_grp = self.nodes_to_node_grp
631
+ end_nodes = {}
632
+ self.each_node { |node| nd_end_nodes = node_grp.dup
633
+ nd_end_nodes.delete(node); end_nodes[node]=nd_end_nodes}
634
+ self.each_node { |start_node|
635
+ node_calc = NodeCalc.new(start_node)
636
+ node_calc.link_filter = @link_filter
637
+ end_nodes[start_node].each_node { |end_node|
638
+ #$PDbgLog.puts_msg "start_node#{start_node},end_node#{
639
+ # end_node}"
640
+ path = node_calc.find_shortest_path_to_node(end_node)
641
+ if (len = path.get_length) > max_path_len
642
+ max_path = path; max_path_len = len
643
+ end
644
+ node_calc.path_cache_each_path { |iter|
645
+ if (nd1 = iter.pop)
646
+ nd1 = nd1.node
647
+ while (nd2 = iter.pop)
648
+ end_nodes[nd1].delete(nd2=nd2.node)
649
+ end_nodes[nd2].delete(nd1)
650
+ end
651
+ end
652
+ }
653
+ }
654
+ }
655
+ #$PDbgLog.sig_return("max_path(#{max_path_len.inspect}): #{
656
+ # max_path ? max_path.to_s(1) : max_path.inspect}")
657
+ max_path
658
+ end
659
+
660
+ cache_get! :get_a_longest_path
661
+
662
+ def get_node_islands(dyke_set)
663
+ #$PDbgLog.sig_call(self)
664
+ #$PDbgLog.puts_msg self.to_s
665
+ #$PDbgLog.puts_msg 'Dyke set: ' + dyke_set.to_s
666
+ assigned = Set.new(dyke_set)
667
+ islands = []
668
+ dyke_set.each { |m|
669
+ #$PDbgLog.print_msg "m#{m} "
670
+ links = @node2links[m]
671
+ m.conns.each_key_value { |conn_k, conn|
672
+ if links[conn_k] && !assigned.include?(conn.exit)
673
+ island = NodeGrp.new; island << conn.exit
674
+ tail = [conn.exit]
675
+ while !tail.empty?
676
+ node = tail.pop
677
+ lks = @node2links[node]
678
+ node.conns.each_key_value { |cn_k, cn|
679
+ if lks[cn_k] && !assigned.include?(cn.exit)
680
+ island << cn.exit
681
+ assigned << cn.exit
682
+ tail.push(cn.exit)
683
+ end
684
+ }
685
+ end
686
+ end
687
+ }
688
+ }
689
+ #$PDbgLog.sig_return
690
+ islands
691
+ end
692
+
693
+ def get_link_islands(dyke_set)
694
+ #$PDbgLog.sig_call(self)
695
+ #$PDbgLog.puts_msg self.to_s
696
+ #$PDbgLog.puts_msg 'Dyke set: ' + dyke_set.to_s
697
+ assigned = Set.new(dyke_set)
698
+ islands = []
699
+ dyke_set.each { |m|
700
+ #$PDbgLog.print_msg "m#{m} "
701
+ links = @node2links[m]
702
+ m.conns.each_key_value { |conn_k, conn|
703
+ if links[conn_k] && !assigned.include?(conn.exit)
704
+ island = LinkGrp.new
705
+ tail = [conn.exit]
706
+ while !tail.empty?
707
+ node = tail.pop
708
+ lks = @node2links[node]
709
+ node.conns.each_key_value { |cn_k, cn|
710
+ if lks[cn_k] && !dyke_set.include?(cn.exit)
711
+ islands << NodeLink.new(node, cn_k)
712
+ tail.push(cn.exit) unless
713
+ assigned.include?(cn.exit)
714
+ end
715
+ }
716
+ assigned << node
717
+ end
718
+ end
719
+ }
720
+ }
721
+ #$PDbgLog.sig_return
722
+ islands
723
+ end
724
+
725
+ def find_first_path_to(dest, max_distc=1.0/0.0)
726
+ return nil if max_distc < 0
727
+ if dest.kind_of?(Proc)
728
+ dest_proc = dest
729
+ else
730
+ dest_proc = proc { |nd| dest.node_eql?(nd) }
731
+ end
732
+ c_paths = {}
733
+ tail = PMinHeap.new { |a,b| a[1] <=> b[1] }
734
+ self.each_node { |m| c_paths[m] = [0, nil]; tail.push([m, 0]) }
735
+ while !tail.empty?
736
+ node, lev = *tail.pop
737
+ if dest_proc.call(node)
738
+ return NodeCalc.path_cache_get_path(node, c_paths)
739
+ end
740
+ next if c_paths.include?(node) && c_paths[node][0] <=lev
741
+ node.conns.each_key_value { |conn_k, conn|
742
+ if (c_lev = lev + conn.length) <= max_distc &&
743
+ !c_paths.include?(conn.exit) ||
744
+ c_paths[conn.exit][0] > c_lev
745
+ c_paths[conn.exit] = [c_lev, NodeLink.
746
+ new(node, conn_k)]
747
+ tail.push([conn.exit, c_lev])
748
+ end
749
+ }
750
+ end
751
+ nil
752
+ end
753
+
754
+ def get_islands_min_span_grp(islands)
755
+ return nil if islands.empty?
756
+ node2grp = {}
757
+ islands.each { |isl| isl.each { |m| node2grp[m] = isl } }
758
+ res = NodeGrp.new(islands.first)
759
+ tail = PMinHeap.new { |a,b| a[1] <=> b[1] }
760
+ c_paths = {}
761
+ res.each { |m| tail.push([m, 0]); c_paths[m] = [0, nil] }
762
+ grps_left = islands.length - 1
763
+ while grps_left > 0
764
+ lev, node = *tail.pop
765
+ node.conns.each_key_value { |conn_k, conn|
766
+ c_lev = lev + conn.length
767
+ if !c_paths.include?(conn.exit) ||
768
+ c_paths[conn.exit][0] > c_lev
769
+ if (grp = node2grp[conn.exit]) &&
770
+ grp.object_id != res.object_id
771
+ grp.each{|m| res << m; node2grp[m]=res
772
+ c_paths[m] = [0, nil]
773
+ tail.push([m, 0])
774
+ }
775
+ grps_left -= 1
776
+ to_link = c_paths[node][1]
777
+ while to_link
778
+ res << to_link.node
779
+ node2grp[to_link.node] = res
780
+ to_link=c_paths[to_link.node][1]
781
+ end
782
+ end
783
+ else
784
+ c_paths[conn.exit] =
785
+ [c_lev, NodeLink.new(node, conn_k)]
786
+ tail.push([c_lev, conn.exit])
787
+ end
788
+ }
789
+ end
790
+ res
791
+ end
792
+
793
+ def get_islands_min_span_paths(islands)
794
+ res = []
795
+ return res if islands.empty?
796
+ node2grp = {}
797
+ islands.each { |isl| isl.each_node { |m| node2grp[m] = isl } }
798
+ grp0 = NodeGrp.new(islands.first)
799
+ tail = PMinHeap.new { |a,b| a[1] <=> b[1] }
800
+ c_paths = {}
801
+ grp0.each_node { |m| tail.push([m, 0]); c_paths[m] = [0, nil] }
802
+ grps_left = islands.length - 1
803
+ while grps_left > 0
804
+ lev, node = *tail.pop
805
+ links = @node2links[node]
806
+ node.conns.each_key_value { |conn_k, conn|
807
+ next unless links[conn_k]
808
+ c_lev = lev + conn.length
809
+ if !c_paths.include?(conn.exit) ||
810
+ c_paths[conn.exit][0] > c_lev
811
+ if (grp = node2grp[conn.exit]) &&
812
+ grp.object_id != res.object_id
813
+ grp.each{|m| node2grp[m]=grp0
814
+ c_paths[m] = [0, nil]
815
+ tail.push([m, 0])
816
+ }
817
+ grps_left -= 1
818
+ path = NodePath.new
819
+ to_link = c_paths[node][1]
820
+ while to_link
821
+ path << to_link
822
+ node2grp[to_link.node] = grp0
823
+ to_link=c_paths[to_link.node][1]
824
+ end
825
+ path.reverse_links!
826
+ res << path
827
+ end
828
+ else
829
+ c_paths[conn.exit] =
830
+ [c_lev, NodeLink.new(node, conn_k)]
831
+ tail.push([c_lev, conn.exit])
832
+ end
833
+ }
834
+ end
835
+ res
836
+ end
837
+ end
838
+
839
+ class NodePath
840
+ def to_node_grp
841
+ res = NodeGrp.new
842
+ self.each { |link| res << link.node }
843
+ res << self.exit
844
+ res
845
+ end
846
+
847
+ def to_link_grp
848
+ res = LinkGrp.new
849
+ self.each { |link| res << link }
850
+ res
851
+ end
852
+
853
+ def undir_to_link_grp
854
+ res = LinkGrp.new
855
+ self.each { |link| res << link
856
+ begin
857
+ res << link.reverse
858
+ rescue NoReverseLinkError
859
+ end
860
+ }
861
+ res
862
+ end
863
+ end
864
+
865
+ end