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,534 @@
1
+ require 'set'
2
+ require 'pav/pix'
3
+ require 'pav/pix/node'
4
+ require 'pav/pix/curve'
5
+ require 'pav/attr_cache'
6
+ require 'pav/pix/contour'
7
+ require 'pav/pix/node_grp'
8
+
9
+ module PPix
10
+
11
+ class ShavedCoreCalc
12
+ attr_accessor :shaved_core, :curve, :min_branch_len, :min_lp_len_min,
13
+ :visited, :node_map
14
+
15
+ def initialize(shaved_core)
16
+ @shaved_core = shaved_core
17
+ @curve = @shaved_core.curve
18
+ @min_branch_len = @shaved_core.min_branch_len
19
+ @min_lp_len_min = @shaved_core.min_lp_len_min
20
+ @visited = {}
21
+ @use_progr = false
22
+ @dup_grps = []
23
+ @orig_grps = []
24
+ @node2gid = {}
25
+ @node_conn_depths = {}
26
+ @node_map = {}
27
+ end
28
+
29
+ def node_dir_max_depth(node, to_parent_conn_is, visited={})
30
+ #$PDbgLog.sig_call(self)
31
+ #$PDbgLog.print_msg "node#{node}, to_parent_conn_is: #{
32
+ # to_parent_conn_is.inspect}: "
33
+ if visited.include?(node)
34
+ #$PDbgLog.sig_return(1.0/0.0)
35
+ return 1.0/0.0
36
+ end
37
+ visited[node] = true
38
+ max_depth = 0
39
+ node.conns.each_with_index { |conn, conn_i|
40
+ next if to_parent_conn_is.include?(conn_i)
41
+ depth = self.node_conn_max_depth(node, conn_i, visited)
42
+ max_depth = depth if depth > max_depth
43
+ }
44
+ visited.delete(node)
45
+ #$PDbgLog.sig_return#("#{node}: #{max_depth}")
46
+ max_depth
47
+ end
48
+
49
+ def node_conn_max_depth(node, conn_i, visited={})
50
+ #$PDbgLog.sig_call(self)
51
+ if (conn_depths = @node_conn_depths[node])
52
+ if (tmp = conn_depths[conn_i])
53
+ #$PDbgLog.sig_return
54
+ return tmp
55
+ end
56
+ else
57
+ conn_depths = @node_conn_depths[node] = []
58
+ end
59
+ exit = (conn = node.conns[conn_i]).exit
60
+ #$PDbgLog.print_msg "node#{node}, conn[#{conn_i}]: #{conn}: "
61
+ if (nd_gid = @node2gid[node]) && nd_gid == @node2gid[exit] &&
62
+ (path = conn.path).kind_of?(NodePath) &&
63
+ (nd_grp = @orig_grps[nd_gid]).include?(path.first)
64
+ rev_conn_is = []
65
+ exit.conns.each_with_index { |r_conn, r_conn_i|
66
+ rev_conn_is << r_conn_i if
67
+ (r_path = r_conn.path).kind_of?(NodePath) &&
68
+ nd_grp.include?(r_path.first)
69
+ }
70
+ else
71
+ rev_conn_is = [node.to_parent_conn_idx(conn_i)]
72
+ end
73
+ res =
74
+ conn_depths[conn_i] = conn.length +
75
+ self.node_dir_max_depth(exit, rev_conn_is, visited)
76
+ #$PDbgLog.sig_return("#{node},conn[#{conn_i}]: #{conn}: #{res}")
77
+ res
78
+ end
79
+
80
+ def min_lp_get_grp(min_lp_path)
81
+ #$PDbgLog.sig_call(self)
82
+ #$PDbgLog.print_msg "min_lp_path: #{min_lp_path}: "
83
+ res = min_lp_path.undir_to_link_grp
84
+ tail = res.nodes_to_a
85
+ while !tail.empty?
86
+ node = tail.pop
87
+ node.conns.each_with_index { |conn, conn_i|
88
+ if conn.length <= @min_lp_len_min &&
89
+ !res.include?(link = NodeLink.new(node, conn_i))
90
+ begin
91
+ excl_link = link.reverse
92
+ rescue NoReverseLinkError
93
+ res << link
94
+ next
95
+ end
96
+ #$PDbgLog.puts_msg "link(#{link.length}): #{link.
97
+ # to_s(1)}"
98
+ node_calc = NodeCalc.new(conn.exit)
99
+ node_calc.link_filter = proc {|lk| lk != excl_link }
100
+ if (path =node_calc.find_shortest_path_to_node(node,
101
+ @min_lp_len_min - conn.length))
102
+ #$PDbgLog.puts_msg "+=(#{path.get_length}) " +
103
+ # path.to_s
104
+ res << link; res << excl_link
105
+ res.add_undir_path!(path)
106
+ path.each { |lk| tail.push(lk.node) }
107
+ end
108
+ end
109
+ }
110
+ end
111
+ #$PDbgLog.sig_return('= ' + res.to_s)
112
+ res
113
+ end
114
+
115
+ def dup_node(node)
116
+ #$PDbgLog.sig_call(self)
117
+ if (tmp = @node_map[node])
118
+ #$PDbgLog.sig_return#(tmp.to_s + ' (cached).')
119
+ return tmp
120
+ end
121
+ #$PDbgLog.print_msg node.coords_to_s + ": "
122
+ #$PDbgLog.puts_msg "map: #{@node_map.to_s}, tmp=#{tmp.inspect}"
123
+ lp, len = *node.get_min_lp_n_len(@min_lp_len_min)
124
+ #$PDbgLog.print_msg "lp(#{len.inspect}): #{lp}: "
125
+ if lp
126
+ #$PDbgLog.puts_msg 'condensing group.'
127
+ grp = self.min_lp_get_grp(lp)
128
+ grp.each { |m|
129
+ if @node_map.include?(m)
130
+ raise "BUG: Group member #{m} already in " +
131
+ "visited: #{grp.node_cnt < 100 ?
132
+ "m's grp.: " + grp.to_s + '. ' : ''}#{
133
+ @node2gid.include?(m) ? (
134
+ @dup_grps[@node2gid[m]].length<100 ?
135
+ @dup_grps[@node2gid[m]].to_s : 'large') :
136
+ ''}!" #'
137
+ end
138
+ }
139
+ if (entries = grp.get_entries_grp).empty?
140
+ #$PDbgLog.puts_msg 'Whole graph is one group.'
141
+ entries = grp
142
+ l_len = @min_lp_len_min#Don't neglect grp.extent
143
+ else
144
+ #$PDbgLog.puts_msg 'Entries: ' + Xy.path_to_s(
145
+ # entries.to_a.sort)
146
+ end
147
+ if (l_path = grp.get_a_longest_path)
148
+ l_len = l_path.get_length
149
+ else
150
+ #$PDbgLog.puts_msg 'A one-node loop group.'
151
+ l_len = -1 # Neglect group's extent.
152
+ end
153
+ # $PDbgLog.print_msg "longest_path(#{l_len}): #{l_path}: "
154
+ if l_len < @min_lp_len_min
155
+ #$PDbgLog.puts_msg 'group extent negligible.'
156
+ gid = @dup_grps.length
157
+ @dup_grps << (new_grp = NodeGrp.new)
158
+ @orig_grps << grp
159
+ entries.each_node { |m|
160
+ raise "BUG: Group entry already duplicated: #{m
161
+ }!" if @node_map[m]
162
+ new_grp <<(@node_map[m]=AaXyNode.new(m.ax,m.ay,[]))}
163
+ new_grp.each { |m| @node2gid[m] = gid }
164
+ entries.each_node { |m| nd_conns = @node_map[m].conns
165
+ grp.get_node_paths_to_entries(m).each { |path|
166
+ raise "BUG: Group entry not duplicated: #{
167
+ path.exit}!" unless @node_map[path.exit]
168
+ cn = NodeConn.new(@node_map[path.exit],
169
+ path.get_length)
170
+ cn.path = path
171
+ #$PDbgLog.puts_msg "path_to_exterior: #{
172
+ # path.to_s(2)}, conn.: #{cn}"
173
+ nd_conns << cn
174
+ }
175
+ m.conns.each_with_index { |conn, conn_i|
176
+ if !grp.include?(NodeLink.new(m, conn_i))
177
+ #$PDbgLog.puts_msg "link to exterior: #{
178
+ # NodeLink.new(m, conn_i).to_s(1)}"
179
+ cn = NodeConn.new(self.dup_node(
180
+ conn.exit), conn.length)
181
+ cn.path = conn.path
182
+ nd_conns << cn
183
+ end
184
+ }
185
+ }
186
+ #dbg_nodes = entries.nodes_to_a
187
+ else
188
+ #$PDbgLog.puts_msg "group's extent non-negligible."
189
+ paths = [l_path]
190
+ dyke = l_path.to_node_grp.get_vicinity_grp_in_set(
191
+ @min_lp_len_min/2, grp.as_node_set)
192
+ #$PDbgLog.puts_msg "Dyke: #{Xy.path_to_s(dyke.to_a.
193
+ # sort)}"
194
+ grps = grp.get_link_islands(dyke)
195
+ #$PDbgLog.puts_msg "grps: #{grps.join("\n --:")}"
196
+ grps_left_idxs = (0...grps.length).to_a
197
+ while !grps_left_idxs.empty?
198
+ i = 0
199
+ while i < grps_left_idxs.length
200
+ t_grp = grps[grps_left_idxs.at(i)]
201
+ l_path = t_grp.get_a_longest_path
202
+ l_len = l_path.get_length
203
+ #$PDbgLog.puts_msg "l_path(#{l_len}): #{l_path}"
204
+ if l_len < @min_lp_len_min
205
+ grps_left_idxs.delete_at(i)
206
+ else
207
+ paths << l_path
208
+ dk = l_path.to_node_grp.get_vicinity(
209
+ @min_lp_len_min/2)
210
+ dk.each { |m| dyke << m }
211
+ islands = t_grp.get_link_islands(dyke)
212
+ if islands.empty?
213
+ grps_left_idxs.delete_at(i)
214
+ else
215
+ grps[grps_left_idxs.at(i)] = islands.first
216
+ 1.upto(islands.length-1).each { |j|
217
+ grps_left_idxs << grps.length
218
+ grps << islands[j]
219
+ }
220
+ end
221
+ end
222
+ end
223
+ end
224
+ #$PDbgLog.puts_msg "grps: #{grps.join("\n --:")}"
225
+ paths.concat(grp.get_islands_min_span_paths(grps))
226
+ paths_grp = NodeGrp.new
227
+ paths.each { |path|
228
+ path.each { |link| paths_grp << link.node }
229
+ paths_grp << path.exit
230
+ }
231
+ entries.each { |m|
232
+ unless paths_grp.include?(m)
233
+ node_calc = NodeCalc.new(m)
234
+ path =node_calc.find_first_path_to(proc{|nd,lev|
235
+ paths_grp.include?(nd) })
236
+ paths << path
237
+ #$PDbgLog.puts_msg "Path to an entry: path: #{
238
+ # path}"
239
+ path.each { |link| paths_grp << link.node }
240
+ paths_grp << path.exit
241
+ end
242
+ }
243
+ entries.each { |m| @node_map[m] =
244
+ AaXyNode.new(m.ax,m.ay,[]) }
245
+ #dbg_nodes = entries.to_a
246
+ paths.each { |path| path.each { |link| nd=link.node
247
+ @node_map[nd] = AaXyNode.new(nd.ax,nd.ay,[]
248
+ ) unless @node_map.include?(nd)
249
+ #dbg_nodes << nd unless @node_map.include?(nd)
250
+ }
251
+ nd = path.exit
252
+ @node_map[nd] = AaXyNode.new(nd.ax, nd.ay, []
253
+ ) unless @node_map.include?(nd)
254
+ #dbg_nodes << nd unless @node_map.include?(nd)
255
+ }
256
+ #$PDbgLog.print_msg "Adding links: "
257
+ paths.each { |path| path.each { |link|
258
+ #$PDbgLog.print_msg "#{link.to_s(1)} "
259
+ conn = link.conn
260
+ cn = NodeConn.new(@node_map[conn.exit],
261
+ conn.length)
262
+ cn.path = conn.path
263
+ @node_map[link.node].conns << cn
264
+ conn = (link=link.reverse).conn #<-- reverse --
265
+ cn = NodeConn.new(@node_map[conn.exit],
266
+ conn.length)
267
+ cn.path = conn.path
268
+ @node_map[link.node].conns << cn
269
+ } }
270
+ #$PDbgLog.puts_msg '.'
271
+ #$PDbgLog.puts_msg 'Adding conns.: '
272
+ entries.each { |m| nd_conns = @node_map[m].conns
273
+ m.conns.each_with_index { |conn, conn_i|
274
+ #$PDbgLog.print_msg "conn:#{conn.to_s(1)} "
275
+ unless grp.include?(NodeLink.new(m, conn_i))
276
+ nd_conns << (cn=NodeConn.new(
277
+ self.dup_node(conn.exit),conn.length))
278
+ cn.path = conn.path
279
+ end
280
+ }
281
+ }
282
+ #$PDbgLog.puts_msg '.'
283
+ end
284
+ # $PDbgLog.sig_return("#{node.to_s} done: "+dbg_nodes.
285
+ # sort.collect{|nd| @node_map[nd].to_s(1) }.join('. ') +
286
+ # ": #{@node_map[node]}")
287
+ @node_map[node]
288
+ else
289
+ #$PDbgLog.print_msg 'copying node: '
290
+ res = @node_map[node] =
291
+ AaXyNode.new(node.ax, node.ay, conns=[])
292
+ node.conns.each { |conn|
293
+ cn = NodeConn.new(self.dup_node(conn.exit),
294
+ conn.length)
295
+ cn.path = conn.path
296
+ conns << cn
297
+ }
298
+ #$PDbgLog.sig_return(res.to_s(1))
299
+ res
300
+ end
301
+ end
302
+
303
+ def dup_graph(node)
304
+ self.dup_node(node)
305
+ end
306
+
307
+ def expand_path(path)
308
+ (node = path.first.node).clear_rev_conns_cache
309
+ path.each { |link|
310
+ unless @node_map.include?(l_nd = link.node)
311
+ @node_map[l_nd] = AaXyNode.new(l_nd.ax, l_nd.ay, [])
312
+ end
313
+ }
314
+ for link in path
315
+ l_exit = link.exit; l_len = link.length
316
+ unless (l_cns = @node_map[link.node].conns).detect { |cn|
317
+ l_exit.node_eql?(cn.exit) && cn.length == l_len }
318
+ l_cns << (new_conn = NodeConn.new(@node_map[l_exit], l_len))
319
+ new_conn.path = link.path
320
+ end
321
+ end
322
+ end
323
+
324
+ def expand_proxy_paths
325
+ #$PDbgLog.sig_call(self)
326
+ @dup_grps.each { |grp|
327
+ #$PDbgLog.print_msg "Group: #{grp}: "
328
+ grp.each_node { |node|
329
+ #$PDbgLog.print_msg "node#{node}: "
330
+ conn_i = 0
331
+ while conn_i < (conns = node.conns).length
332
+ conn = conns.at(conn_i)
333
+ #$PDbgLog.print_msg "conn: #{conn.to_s(1)} "
334
+ if (path = conn.path).kind_of?(NodePath) &&
335
+ grp.includes_node?(conn.exit)
336
+ #$PDbgLog.print_msg " => expanding path: "
337
+ conns.delete_at(conn_i)
338
+ self.expand_path(path)
339
+ else
340
+ conn_i += 1
341
+ end
342
+ end
343
+ }
344
+ #$PDbgLog.puts_msg '.'
345
+ }
346
+ #$PDbgLog.sig_return
347
+ end
348
+
349
+ def shave_node!(node)
350
+ #$PDbgLog.sig_call(self)
351
+ conns = node.conns
352
+ i1 = i2 = nil
353
+ i1_depth = i2_depth = 0
354
+ i = -1
355
+ while (i += 1) < conns.length
356
+ depth = self.node_conn_max_depth(node, i)
357
+ #$PDbgLog.print_msg node.to_s + ": --" +
358
+ # conns[used_conn_is[i]].last.coords_to_s +
359
+ # ",#{used_conn_is[i]}:#{depth}: "
360
+ if i2
361
+ if depth > i1_depth
362
+ i_min = i2; min_depth = i2_depth
363
+ i2 = i1; i2_depth = i1_depth
364
+ i1 = i; i1_depth = depth
365
+ elsif depth > i2_depth
366
+ i_min = i2; min_depth = i2_depth
367
+ i2 = i; i2_depth = depth
368
+ else
369
+ i_min = i; min_depth = depth
370
+ end
371
+ if min_depth < @min_branch_len
372
+ #$PDbgLog.print_msg "deleting at #{i_min
373
+ # }"
374
+ node.delete_conn(i_min)
375
+ if (c_depths = @node_conn_depths[node])
376
+ c_depths.delete_at(i_min)
377
+ end
378
+ i1 -= 1 if i1 > i_min
379
+ i2 -= 1 if i2 > i_min
380
+ i -= 1
381
+ end
382
+ elsif i1
383
+ if depth > i1_depth
384
+ i2 = i1; i2_depth = i1_depth
385
+ i1 = i; i1_depth = depth
386
+ else
387
+ i2 = i; i2_depth = depth
388
+ end
389
+ else
390
+ i1 = i; i1_depth = depth
391
+ end
392
+ #$PDbgLog.puts_msg "."
393
+ end
394
+ #$PDbgLog.sig_return
395
+ end
396
+
397
+ def shave!(node)
398
+ #$PDbgLog.sig_call(self)
399
+ #$PDbgLog.print_msg node.coords_to_s + ", conns: #{node.conns.
400
+ # join('; ')}: "
401
+ node.conns.each { |conn|
402
+ next if @visited.include?(conn.exit.a_yx)
403
+ self.shave_node!(conn.exit)
404
+ @visited[conn.exit.a_yx] = true
405
+ unless conn.exit.conns.detect { |cn|
406
+ cn.exit.node_eql?(node) }
407
+ #$PDbgLog.sig_return(node.coords_to_s + ": " +
408
+ # (res = self.shave!(conn.last)).coords_to_s)
409
+ return self.shave!(conn.exit) #res
410
+ end
411
+ if !(tmp = self.shave!(conn.exit)).node_eql?(conn.exit)
412
+ #$PDbgLog.sig_return(node.coords_to_s + ": " +
413
+ # tmp.coords_to_s)
414
+ return tmp
415
+ end
416
+ }
417
+ $PDbgLog.progr.progr_units = @visited.length if @use_progr
418
+ #$PDbgLog.sig_return(node.coords_to_s + ": " + node.coords_to_s)
419
+ node
420
+ end
421
+
422
+ def shave_graph(node)
423
+ $PDbgLog.sig_call(self)
424
+ #$PDbgLog.print_msg "node#{node}: "
425
+ @node_map = {}
426
+ unless (wrk_node = self.dup_graph(node))
427
+ # node could have been a non-visitable node in a group.
428
+ @node_map.each_value { |wrk_node| break }
429
+ end
430
+ #$PDbgLog.print_msg "wrk_node#{wrk_node} "
431
+ $PDbgLog.new_progr
432
+ $PDbgLog.progr.total_progr_units = @node_map.length
433
+ $PDbgLog.progr.show_as = "/ node" + (@node_map.length == 1 ?
434
+ '' : 's')
435
+ @use_progr = true
436
+ #$PDbgLog.puts_msg "Duplicated graph: #{wrk_node.graph_to_s}"
437
+ res = self.shave!(wrk_node)
438
+ #$PDbgLog.puts_msg "Shaved graph: #{res.graph_to_s}"
439
+ self.expand_proxy_paths
440
+ #$PDbgLog.print_msg "res#{res} "
441
+ @use_progr = false
442
+ $PDbgLog.sig_return
443
+ res
444
+ end
445
+ end
446
+
447
+ class Curve
448
+ def get_shaved_core(min_branch_len, min_lp_len_min)
449
+ ShavedCore.new(self, min_branch_len, min_lp_len_min)
450
+ end
451
+
452
+ def c_shaved_core(min_hair_len, min_lp_len)
453
+ return @c_shaved_core if @c_shaved_core
454
+ #$PDbgLog.sig_call(self)
455
+ #$PDbgLog.print_msg @shaved_core.inspect
456
+ @c_shaved_core = self.get_shaved_core(min_hair_len, min_lp_len)
457
+ #$PDbgLog.sig_return(@shaved_core.object_id)
458
+ #@c_shaved_core
459
+ end
460
+
461
+ def c_delete_shaved_core
462
+ @c_shaved_core = nil
463
+ end
464
+ end
465
+
466
+ class ShavedCore < ImageObject
467
+ attr_reader :curve, :branches, :min_branch_len, :min_lp_len_min
468
+
469
+ self.img_obj_add_sub_obj :branches
470
+
471
+ def initialize(curve, min_branch_len, min_lp_len_min)
472
+ @curve = curve
473
+ @branches = []
474
+ @min_branch_len = min_branch_len
475
+ @min_lp_len_min = min_lp_len_min
476
+ super()
477
+ self.rebuild
478
+ end
479
+
480
+ def rebuild
481
+ self.clear
482
+ if @curve.length < 2
483
+ self.replace(@curve)
484
+ return
485
+ end
486
+ $PDbgLog.sig_call(self)
487
+ $PDbgLog.print_msg "@min_branch_len=#{@min_branch_len
488
+ }, @min_lp_len_min=#{@min_lp_len_min}; Shaving: "
489
+ calc = ShavedCoreCalc.new(self)
490
+ node = @curve.pix_node(@curve.first)
491
+ node = node.conns.first.exit unless node.conns.empty?
492
+ #$PDbgLog.puts_msg "Graph: #{node.graph_to_s}"
493
+ node = calc.shave_graph(node)
494
+ $PDbgLog.print_msg "done. Traversing: "
495
+ @branches.clear
496
+ branch_start_i = 0
497
+ if node.conns.length < 2
498
+ self << AaPix.new(@curve.pixbuf, node.ax, node.ay)
499
+ else
500
+ node.graph_each_node { |nd|
501
+ if nd.conns.length < 2
502
+ node = nd
503
+ self << AaPix.new(@curve.pixbuf,node.ax,node.ay)
504
+ break
505
+ end
506
+ }
507
+ end
508
+ next_node = node
509
+ #$PDbgLog.puts_msg "node#{node}"
510
+ #$PDbgLog.puts_msg "Final graph: #{node.graph_to_s}"
511
+ node.graph_each_conn_i { |node, conn_i|
512
+ #$PDbgLog.puts_msg "node#{node},conn_i[#{conn_i}]: #{
513
+ # node.conns[conn_i].to_s(2)}: #{node.
514
+ # conns[conn_i].path.expand_to_xy_path.xy_nodes}"
515
+ if !next_node.node_eql?(node) || node.conns.length > 2
516
+ @branches << ImageObject.new(self,
517
+ branch_start_i, self.length)
518
+ #$PDbgLog.puts_msg "Branch: #{Xy.path_to_s(
519
+ # @branches.last)}"
520
+ branch_start_i = self.length
521
+ end
522
+ conn = node.conns[conn_i]
523
+ self.concat(conn.path.expand_to_xy_path.xy_nodes)
524
+ next_node = conn.exit
525
+ }
526
+ @branches << ImageObject.new(self, branch_start_i,
527
+ self.length) unless branch_start_i >= self.length
528
+ #$PDbgLog.print_msg "@branches.length=#{@branches.length
529
+ # }; @branches: #{@branches.inspect} "
530
+ $PDbgLog.sig_return("done all.")
531
+ end
532
+ end
533
+
534
+ end