extract-curves 0.1.1

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 (172) 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/cstr.c +82 -0
  11. data/ruby_ext/pav/cstr.h +17 -0
  12. data/ruby_ext/pav/extconf.rb +22 -0
  13. data/ruby_ext/pav/pav.c +162 -0
  14. data/ruby_ext/pav/pgtk.c +40 -0
  15. data/ruby_ext/pav/pgtk.h +14 -0
  16. data/ruby_ext/pav/pix.c +806 -0
  17. data/ruby_ext/pav/pix.h +236 -0
  18. data/ruby_ext/pav/t.rb +35 -0
  19. data/ruby_ext/pav/t1.rb +35 -0
  20. data/ruby_libs/pav/attr_cache.rb +211 -0
  21. data/ruby_libs/pav/attr_cache.t1.rb +32 -0
  22. data/ruby_libs/pav/cache.rb +31 -0
  23. data/ruby_libs/pav/collection/std.rb +58 -0
  24. data/ruby_libs/pav/dbg_log.rb +458 -0
  25. data/ruby_libs/pav/floatsio.rb +53 -0
  26. data/ruby_libs/pav/generator_cache.rb +165 -0
  27. data/ruby_libs/pav/graph/node.rb +602 -0
  28. data/ruby_libs/pav/graph/node_grp.rb +865 -0
  29. data/ruby_libs/pav/gtk.rb +6 -0
  30. data/ruby_libs/pav/gtk/button.rb +118 -0
  31. data/ruby_libs/pav/gtk/dialog.rb +29 -0
  32. data/ruby_libs/pav/gtk/guiobj.rb +772 -0
  33. data/ruby_libs/pav/gtk/icons.rb +124 -0
  34. data/ruby_libs/pav/gtk/rulers.rb +264 -0
  35. data/ruby_libs/pav/gtk/toolbar.rb +189 -0
  36. data/ruby_libs/pav/guiobj.rb +2 -0
  37. data/ruby_libs/pav/guiobj/info_asm.rb +41 -0
  38. data/ruby_libs/pav/guiobj/method.rb +211 -0
  39. data/ruby_libs/pav/guiobj/obj.rb +134 -0
  40. data/ruby_libs/pav/guiobj/signals.rb +9 -0
  41. data/ruby_libs/pav/heap.rb +54 -0
  42. data/ruby_libs/pav/icons/alt_handle.xcf +0 -0
  43. data/ruby_libs/pav/icons/alt_handle.xpm +3832 -0
  44. data/ruby_libs/pav/icons/alt_handle_hover.xcf +0 -0
  45. data/ruby_libs/pav/icons/alt_handle_hover.xpm +3368 -0
  46. data/ruby_libs/pav/icons/alt_handle_pressed.xcf +0 -0
  47. data/ruby_libs/pav/icons/alt_handle_pressed.xpm +3828 -0
  48. data/ruby_libs/pav/icons/blob.gif +0 -0
  49. data/ruby_libs/pav/icons/clover_base.xcf +0 -0
  50. data/ruby_libs/pav/icons/contour.gif +0 -0
  51. data/ruby_libs/pav/icons/contour.xcf +0 -0
  52. data/ruby_libs/pav/icons/contour_carpet.gif +0 -0
  53. data/ruby_libs/pav/icons/contour_carpet.xcf +0 -0
  54. data/ruby_libs/pav/icons/curve.gif +0 -0
  55. data/ruby_libs/pav/icons/curve.xcf +0 -0
  56. data/ruby_libs/pav/icons/curve_carpet.gif +0 -0
  57. data/ruby_libs/pav/icons/curve_carpet.xcf +0 -0
  58. data/ruby_libs/pav/icons/expand_base.xcf +0 -0
  59. data/ruby_libs/pav/icons/expand_closed.xpm +1791 -0
  60. data/ruby_libs/pav/icons/expand_closed_hover.xpm +1775 -0
  61. data/ruby_libs/pav/icons/expand_open.xpm +1788 -0
  62. data/ruby_libs/pav/icons/expand_open_hover.xpm +1752 -0
  63. data/ruby_libs/pav/icons/extract_curves/extract_curves-icon-rgb.ppm +14 -0
  64. data/ruby_libs/pav/icons/extract_curves/extract_curves-logo-rgb.gif +0 -0
  65. data/ruby_libs/pav/icons/extract_curves/extract_curves-logo-rgb.xcf +0 -0
  66. data/ruby_libs/pav/icons/extract_curves/trace_mark.xcf +0 -0
  67. data/ruby_libs/pav/icons/extract_curves/trace_mark.xpm +38 -0
  68. data/ruby_libs/pav/icons/handle.xcf +0 -0
  69. data/ruby_libs/pav/icons/handle.xpm +213 -0
  70. data/ruby_libs/pav/icons/loop.gif +0 -0
  71. data/ruby_libs/pav/icons/loop.xcf +0 -0
  72. data/ruby_libs/pav/icons/loop_carpet.gif +0 -0
  73. data/ruby_libs/pav/icons/loop_carpet.xcf +0 -0
  74. data/ruby_libs/pav/icons/next.xpm +29 -0
  75. data/ruby_libs/pav/icons/next_hover.xpm +315 -0
  76. data/ruby_libs/pav/icons/next_pressed.xpm +144 -0
  77. data/ruby_libs/pav/icons/prev.xpm +29 -0
  78. data/ruby_libs/pav/icons/prev_hover.xpm +315 -0
  79. data/ruby_libs/pav/icons/prev_pressed.xpm +144 -0
  80. data/ruby_libs/pav/icons/shaved-core.gif +0 -0
  81. data/ruby_libs/pav/icons/vnext.xpm +29 -0
  82. data/ruby_libs/pav/icons/vprev.xpm +29 -0
  83. data/ruby_libs/pav/numeric/ext.rb +21 -0
  84. data/ruby_libs/pav/patterns/hsep.gif +0 -0
  85. data/ruby_libs/pav/patterns/tnode.gif +0 -0
  86. data/ruby_libs/pav/patterns/tnode_w_link.gif +0 -0
  87. data/ruby_libs/pav/patterns/vlink.gif +0 -0
  88. data/ruby_libs/pav/patterns/vsep.gif +0 -0
  89. data/ruby_libs/pav/patterns/yg_hrope.xpm +492 -0
  90. data/ruby_libs/pav/patterns/yg_hrope_thick.xpm +1904 -0
  91. data/ruby_libs/pav/patterns/yg_hrope_thin.xpm +130 -0
  92. data/ruby_libs/pav/patterns/yg_tnode.xpm +180 -0
  93. data/ruby_libs/pav/patterns/yg_tnode_thick.xpm +615 -0
  94. data/ruby_libs/pav/patterns/yg_tnode_thin.xpm +55 -0
  95. data/ruby_libs/pav/patterns/yg_tnode_w_link.xpm +190 -0
  96. data/ruby_libs/pav/patterns/yg_tnode_w_link_thick.xpm +676 -0
  97. data/ruby_libs/pav/patterns/yg_tnode_w_link_thin.xpm +62 -0
  98. data/ruby_libs/pav/patterns/yg_vrope.xpm +563 -0
  99. data/ruby_libs/pav/patterns/yg_vrope_thick.xpm +2047 -0
  100. data/ruby_libs/pav/patterns/yg_vrope_thin.xpm +166 -0
  101. data/ruby_libs/pav/pav_find.rb +90 -0
  102. data/ruby_libs/pav/pix.rb +402 -0
  103. data/ruby_libs/pav/pix/aapix.rb +378 -0
  104. data/ruby_libs/pav/pix/blob.rb +678 -0
  105. data/ruby_libs/pav/pix/circle.rb +73 -0
  106. data/ruby_libs/pav/pix/contour.rb +676 -0
  107. data/ruby_libs/pav/pix/contour/calc_situations.rb +9 -0
  108. data/ruby_libs/pav/pix/contour/carp_calc.rb +212 -0
  109. data/ruby_libs/pav/pix/contour/situations.dmp +0 -0
  110. data/ruby_libs/pav/pix/contour/situations.rb +21 -0
  111. data/ruby_libs/pav/pix/curve.rb +1544 -0
  112. data/ruby_libs/pav/pix/img_obj.rb +865 -0
  113. data/ruby_libs/pav/pix/node.rb +159 -0
  114. data/ruby_libs/pav/pix/shaved_core.rb +697 -0
  115. data/ruby_libs/pav/pix/subpix.rb +212 -0
  116. data/ruby_libs/pav/rand_accessible.rb +16 -0
  117. data/ruby_libs/pav/rangeset.rb +63 -0
  118. data/ruby_libs/pav/search.rb +210 -0
  119. data/ruby_libs/pav/set.rb +130 -0
  120. data/ruby_libs/pav/string/bits.rb +523 -0
  121. data/ruby_libs/pav/string/ext.rb +58 -0
  122. data/ruby_libs/pav/string/observable.rb +155 -0
  123. data/ruby_libs/pav/string/text.rb +79 -0
  124. data/ruby_libs/pav/string/words.rb +42 -0
  125. data/ruby_libs/pav/sub_arr.rb +56 -0
  126. data/ruby_libs/pav/traced_obj.rb +79 -0
  127. data/web/index.html +280 -0
  128. data/web/media/icons/alt_handle.xcf +0 -0
  129. data/web/media/icons/alt_handle.xpm +3832 -0
  130. data/web/media/icons/alt_handle_hover.xcf +0 -0
  131. data/web/media/icons/alt_handle_hover.xpm +3368 -0
  132. data/web/media/icons/alt_handle_pressed.xcf +0 -0
  133. data/web/media/icons/alt_handle_pressed.xpm +3828 -0
  134. data/web/media/icons/blob.gif +0 -0
  135. data/web/media/icons/clover_base.xcf +0 -0
  136. data/web/media/icons/contour.gif +0 -0
  137. data/web/media/icons/contour.xcf +0 -0
  138. data/web/media/icons/contour_carpet.gif +0 -0
  139. data/web/media/icons/contour_carpet.xcf +0 -0
  140. data/web/media/icons/curve.gif +0 -0
  141. data/web/media/icons/curve.xcf +0 -0
  142. data/web/media/icons/curve_carpet.gif +0 -0
  143. data/web/media/icons/curve_carpet.xcf +0 -0
  144. data/web/media/icons/expand_base.xcf +0 -0
  145. data/web/media/icons/expand_closed.xpm +1791 -0
  146. data/web/media/icons/expand_closed_hover.xpm +1775 -0
  147. data/web/media/icons/expand_open.xpm +1788 -0
  148. data/web/media/icons/expand_open_hover.xpm +1752 -0
  149. data/web/media/icons/extract_curves/extract_curves-icon-rgb.ppm +14 -0
  150. data/web/media/icons/extract_curves/extract_curves-logo-rgb.gif +0 -0
  151. data/web/media/icons/extract_curves/extract_curves-logo-rgb.xcf +0 -0
  152. data/web/media/icons/extract_curves/trace_mark.xcf +0 -0
  153. data/web/media/icons/extract_curves/trace_mark.xpm +38 -0
  154. data/web/media/icons/handle.xcf +0 -0
  155. data/web/media/icons/handle.xpm +213 -0
  156. data/web/media/icons/loop.gif +0 -0
  157. data/web/media/icons/loop.xcf +0 -0
  158. data/web/media/icons/loop_carpet.gif +0 -0
  159. data/web/media/icons/loop_carpet.xcf +0 -0
  160. data/web/media/icons/next.xpm +29 -0
  161. data/web/media/icons/next_hover.xpm +315 -0
  162. data/web/media/icons/next_pressed.xpm +144 -0
  163. data/web/media/icons/prev.xpm +29 -0
  164. data/web/media/icons/prev_hover.xpm +315 -0
  165. data/web/media/icons/prev_pressed.xpm +144 -0
  166. data/web/media/icons/shaved-core.gif +0 -0
  167. data/web/media/icons/vnext.xpm +29 -0
  168. data/web/media/icons/vprev.xpm +29 -0
  169. data/web/media/title.jpeg +0 -0
  170. data/web/media/title.xcf +0 -0
  171. data/web/stylesheets/default.css +20 -0
  172. metadata +229 -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