extract-curves 0.1.1-i586-linux

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 (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.so +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 'ostruct'
3
+ require 'pav/pix'
4
+ require 'pav/heap'
5
+ require 'pav/guiobj'
6
+
7
+ module PPix
8
+
9
+ module MPixbufPix
10
+ def img_obj_subpix8(sub_n)
11
+ # @img_obj_subpix8 = [] unless @img_obj_subpix8
12
+ # tmp = @img_obj_subpix8[sub_n]
13
+ # return tmp if tmp
14
+ #$PDbgLog.sig_call(self)
15
+ #$PDbgLog.puts_msg self.coords_to_s + ", sub_n=#{sub_n}"
16
+ #res =
17
+ #@img_obj_subpix8[sub_n] =
18
+ ImageObjectSubpix.new(Subpix8.new(self, sub_n))
19
+ #$PDbgLog.puts_msg res.inspect
20
+ #$PDbgLog.sig_return
21
+ #res
22
+ end
23
+
24
+ def connections(&get_neighbs)
25
+ #$PDbgLog.sig_call(self)
26
+ #$PDbgLog.print_msg(self.coords_to_s)
27
+ res = []
28
+ visited = {}
29
+ for neighb in yield(self)
30
+ #$PDbgLog.print_msg " neighb#{neighb.coords_to_s}: "
31
+ next if visited.include?(neighb.a_yx)
32
+ res << [tmp_pix=neighb]
33
+ prev_pix = self
34
+ while (pix_ngbs = yield(tmp_pix)).length == 2
35
+ if pix_ngbs.first.a_eql?(prev_pix)
36
+ prev_pix = tmp_pix
37
+ tmp_pix = pix_ngbs.last
38
+ else
39
+ prev_pix = tmp_pix
40
+ tmp_pix = pix_ngbs.first
41
+ end
42
+ res.last << tmp_pix
43
+ if self.a_eql?(tmp_pix)
44
+ visited[prev_pix.a_yx] = true
45
+ break
46
+ end
47
+ end
48
+ #$PDbgLog.puts_msg "."
49
+ end
50
+ #$PDbgLog.sig_return
51
+ res
52
+ end
53
+
54
+ def rev_conn_idx(conns, conn_i, rev_conns)
55
+ #$PDbgLog.sig_call(self)
56
+ #$PDbgLog.puts_msg "(#{conn_i}) from (#{self.x}, #{self.y})."
57
+ path = conns[conn_i]
58
+ #$PDbgLog.puts_msg "path: #{PixbufPix.path_to_s(path)}"
59
+ end_pix = path.last
60
+ if self.a_eql?(end_pix)
61
+ return conn_i
62
+ else
63
+ path = path.reverse[1, path.length-1] << self
64
+ #$PDbgLog.puts_msg "rev_path: #{
65
+ # PixbufPix.path_to_s(path)}"
66
+ rev_conns.each_with_index { |rev_conn, i|
67
+ #$PDbgLog.puts_msg "rev_conn: #{
68
+ # PixbufPix.path_to_s(rev_conn)}"
69
+ if PixbufPix.a_paths_eql?(path, rev_conn)
70
+ return i
71
+ end
72
+ }
73
+ end
74
+ #$PDbgLog.sig_return
75
+ nil
76
+ end
77
+
78
+ def find_shortest_pix_path_to(dest, levs_left=-1, &get_neighbs)
79
+ #$PDbgLog.sig_call(self)
80
+ if dest.kind_of?(Proc)
81
+ dest_proc = dest
82
+ else
83
+ dest_proc = proc { |px| px.y==dest.y && px.x==dest.x }
84
+ end
85
+ path_cache = { self.yx => 0 }
86
+ tail = [[self, 0]]
87
+ #$PDbgLog.print_msg "dest=#{dest}, from #{
88
+ # self.coords_to_s}, levs_left=#{levs_left}: "
89
+ if levs_left == 0
90
+ #$PDbgLog.sig_return("levs_left==0: nil")
91
+ return nil
92
+ end
93
+ while !tail.empty?
94
+ pix, lev = *tail.shift
95
+ #if lev > 100
96
+ #$PDbgLog.print_msg
97
+ #puts "dest=#{dest}, from #{
98
+ # self.coords_to_s}, levs_left=#{levs_left}: #{tail.
99
+ # length},#{pix.coords_to_s},#{lev}; "
100
+ #end
101
+ # $PDbgLog.print_msg "#{tail.length},#{pix.coords_to_s},#{
102
+ # lev}; "
103
+ if dest_proc.call(pix)
104
+ res = []
105
+ i = path_cache[pix.yx]
106
+ while i > 0
107
+ res[i-=1] = pix
108
+ yield(pix).each { |pix|
109
+ break if path_cache[pix.yx] == i
110
+ }
111
+ end
112
+ #$PDbgLog.sig_return(PixbufPix.path_to_s(res))
113
+ return res
114
+ end
115
+ yield(pix).each { |neighb|
116
+ unless (path_cache.include?(neighb.yx) &&
117
+ path_cache[neighb.yx] <= lev+1) ||
118
+ lev+1 == levs_left
119
+ tail.push([neighb, lev+1])
120
+ path_cache[neighb.yx] = lev+1
121
+ end
122
+ }
123
+ end
124
+ #$PDbgLog.sig_return("nil")
125
+ nil
126
+ end
127
+
128
+ def find_shortest_pix_path_into(res, dest, levs_left=-1, path_cache={},
129
+ tail=[], neighbs=[]) # &get_neighbs
130
+ #$PDbgLog.sig_call(self)
131
+ if dest.kind_of?(Proc)
132
+ dest_proc = dest
133
+ else
134
+ dest_proc = proc { |px| px.y==dest.y && px.x==dest.x }
135
+ end
136
+ path_cache.clear; path_cache[self.yx] = 0
137
+ tail.clear; tail << self << 0
138
+ #$PDbgLog.print_msg "dest=#{dest}, from #{
139
+ # self.coords_to_s}, levs_left=#{levs_left}: "
140
+ if levs_left == 0
141
+ #$PDbgLog.sig_return("levs_left==0: nil")
142
+ return nil
143
+ end
144
+ while !tail.empty?
145
+ pix = tail.shift; lev = tail.shift
146
+ #if lev > 100
147
+ #$PDbgLog.print_msg
148
+ #puts "dest=#{dest}, from #{
149
+ # self.coords_to_s}, levs_left=#{levs_left}: #{tail.
150
+ # length},#{pix.coords_to_s},#{lev}; "
151
+ #end
152
+ # $PDbgLog.print_msg "#{tail.length},#{pix.coords_to_s},#{
153
+ # lev}; "
154
+ if dest_proc.call(pix)
155
+ res.clear
156
+ i = path_cache[pix.yx]
157
+ while i > 0
158
+ res[i-=1] = pix
159
+ yield(pix, neighbs).each { |pix|
160
+ break if path_cache[pix.yx] == i
161
+ }
162
+ end
163
+ #$PDbgLog.sig_return(PixbufPix.path_to_s(res))
164
+ return res
165
+ end
166
+ yield(pix, neighbs).each { |neighb|
167
+ unless (path_cache.include?(neighb.yx) &&
168
+ path_cache[neighb.yx] <= lev+1) ||
169
+ lev+1 == levs_left
170
+ tail << neighb << (lev+1)
171
+ path_cache[neighb.yx] = lev+1
172
+ end
173
+ }
174
+ end
175
+ #$PDbgLog.sig_return("nil")
176
+ nil
177
+ end
178
+
179
+ def find_first_path_to(dest, max_lev=1.0/0.0, &get_neighbs_levs)
180
+ $PDbgLog.sig_call(self)
181
+ if dest.kind_of?(Proc)
182
+ dest_proc = dest
183
+ else
184
+ dest_proc = proc { |px| dest.a_eql?(px) }
185
+ end
186
+ path_cache = { self.a_yx => [nil, 0] }
187
+ tail = PMinHeap.new { |frm1,frm2| frm1[1] <=> frm2[1] }
188
+ tail.push([self, 0])
189
+ if max_lev < 1
190
+ $PDbgLog.sig_return("max_lev < 1: nil")
191
+ return nil
192
+ end
193
+ while !tail.empty?
194
+ pix, lev = *tail.pop
195
+ if dest_proc.call(pix, lev)
196
+ frm = path_cache[pix.a_yx]
197
+ res = [pix]
198
+ while frm[0]
199
+ res << frm[0]
200
+ frm = path_cache[frm[0].a_yx]
201
+ end
202
+ $PDbgLog.sig_return(PixbufPix.path_to_s(
203
+ res.reverse))
204
+ return res.reverse!
205
+ end
206
+ yield(pix, lev).each { |args| neighb, neighb_lev = *args
207
+ unless (path_cache.include?(neighb.a_yx) &&
208
+ path_cache[neighb.a_yx][1] <= neighb_lev) ||
209
+ neighb_lev > max_lev
210
+ tail.push([neighb, neighb_lev])
211
+ path_cache[neighb.a_yx]=[pix,neighb_lev]
212
+ end
213
+ }
214
+ end
215
+ $PDbgLog.sig_return("nil")
216
+ nil
217
+ end
218
+
219
+ def inspect
220
+ idmem = self.object_id & ( (1 << (8*self.object_id.size)) - 1 )
221
+ "<#{self.class.name}:0x%x #{self.coords_to_s}" % idmem +
222
+ "#{self.instance_variables.collect { |var| " " + var + "=" +
223
+ self.instance_variable_get(var).inspect }.join(",")}>"
224
+ end
225
+ end
226
+
227
+ class ImageObjectSubpix #< ImageObjectPix
228
+ attr_reader :subpix, :ppix
229
+
230
+ def initialize(subpix)
231
+ @subpix = subpix
232
+ super(subpix.img_pix)
233
+ @ppix = ppix
234
+ end
235
+
236
+ def method_missing(id, *args, &block)
237
+ begin
238
+ @subpix.send(id, *args, &block)
239
+ rescue NoMethodError
240
+ @subpix.img_pix.send(id, *args, &block)
241
+ end
242
+ end
243
+
244
+ def to_s
245
+ @subpix.to_s
246
+ end
247
+
248
+ def inspect
249
+ idmem = self.object_id & ( (1 << (8*self.object_id.size)) - 1 )
250
+ "<#{self.class.name}:0x%x @subpix#{@subpix.to_s}"%idmem +
251
+ "#{self.instance_variables.collect{|var|"#{var}=#{self.
252
+ instance_variable_get(var).inspect}"}.join(",")}>" #"
253
+ end
254
+ end
255
+
256
+ class ImageObject
257
+ include PGuiObj::MObj
258
+
259
+ def self.create_array(arr)
260
+ PGuiObj::ObjArray.create(arr, [], OpenStruct.new(
261
+ 'marshal_dump_btn' => false, 'dump_to_s_btn' => false,
262
+ 'dump_inspect_btn' => false))
263
+ end
264
+
265
+ def self.write_objs(file, format, objs)
266
+ #$PDbgLog.sig_call(self)
267
+ #$PDbgLog.puts_msg "file: #{file.inspect}, obj: #{obj}"
268
+ if format[0].kind_of?(String) && format[0].downcase == 'txt'
269
+ if file.kind_of?(String)
270
+ open(file, format[1]) { |file| objs.each { |obj|
271
+ obj.each { |pix| file.puts "#{pix.ax}\t#{pix.ay}" }
272
+ }}
273
+ else
274
+ objs.each { |obj|
275
+ obj.each { |pix| file.puts "#{pix.ax}\t#{pix.ay}" }
276
+ }
277
+ end
278
+ else
279
+ #outp_buf = PPix::Pixbuf.new(Gdk::Pixbuf::COLORSPACE_RGB,
280
+ # false, 8, format[0], format[1])
281
+ #pixels = outp_buf.pixels
282
+ #rowstride = outp_buf.rowstride
283
+ #pix_len = outp_buf.pix_length
284
+ outp_buf = Gdk::Image.new(Gdk::Image::FASTEST,
285
+ Gdk::Visual.best, width=format[0], height=format[1])
286
+ white = ~0
287
+ objs.each { |obj| obj.each { |pix|
288
+ ax = pix.ax; ay = pix.ay
289
+ x1 = ax.floor; y1 = ay.floor
290
+ x2 = ax.ceil; y2 = ay.ceil
291
+ outp_buf.put_pixel(x1, y1, white) if x1 >= 0 &&
292
+ x1 < width && y1 >= 0 && y1 < height
293
+ if x1 != x2
294
+ if y1 != y2
295
+ outp_buf.put_pixel(x2, y1, white) if x2 >= 0 &&
296
+ x2 < width && y1 >= 0 && y1 < height
297
+ outp_buf.put_pixel(x1, y2, white) if x1 >= 0 &&
298
+ x1 < width && y2 >= 0 && y2 < height
299
+ outp_buf.put_pixel(x2, y2, white) if x2 >= 0 &&
300
+ x2 < width && y2 >= 0 && y2 < height
301
+ else
302
+ outp_buf.put_pixel(x2, y1, white) if x2 >= 0 &&
303
+ x2 < width && y1 >= 0 && y1 < height
304
+ end
305
+ elsif y1 != y2
306
+ outp_buf.put_pixel(x1, y2, white) if x1 >= 0 &&
307
+ x1 < width && y2 >= 0 && y2 < height
308
+ end
309
+ } }
310
+ if file.kind_of?(String)
311
+ Gdk::Pixbuf.from_image(
312
+ Gdk::Colormap.new(Gdk::Visual.best, true), outp_buf,
313
+ 0, 0, format[0], format[1], nil, 0, 0).
314
+ save(file, format[2])
315
+ else
316
+ file.write(outp_buf.save_to_buffer(format[2]))
317
+ end
318
+ end
319
+ #$PDbgLog.sig_return
320
+ end
321
+
322
+ def self.save_objs(pixbuf_width, pixbuf_height, objs)
323
+ dialog = Gtk::FileChooserDialog.new("Save image object to file",
324
+ nil, Gtk::FileChooser::ACTION_SAVE, "gnome-vfs",
325
+ [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT],
326
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL])
327
+ dialog.preview_widget_active = false
328
+ dialog.default_response = Gtk::Dialog::RESPONSE_ACCEPT
329
+ dialog.set_extra_widget(fmt_hbox = Gtk::HBox.new(false, 0))
330
+ fmt_hbox.pack_start(Gtk::Label.new('Output format: '), false,
331
+ false, 0)
332
+ fmt_hbox.pack_start(fmt_combo = Gtk::ComboBox.new,false,false,0)
333
+ fmt_combo.append_text('Auto (by extension)')
334
+ fmt_combo.append_text('Tab-separated text (.txt)')
335
+ fmt_hbox.show_all
336
+ fmts = {}
337
+ i = 2
338
+ PPix::Pixbuf.formats.each { |fmt|
339
+ fmt_combo.append_text("#{fmt.description} (.#{fmt.name})")
340
+ fmts[fmt.name] = i
341
+ fmts[i] = fmt.name
342
+ i += 1
343
+ }
344
+ fmts['txt'] = 1
345
+ fmt_combo.active = 0
346
+ fmt_active = nil
347
+ path = nil
348
+ sel_proc = proc { |path|
349
+ if fmt_combo.active == 0
350
+ if path && (dot_idx = path.rindex('.'))
351
+ if (fmt_active = fmts[path[dot_idx+1...path.length]])
352
+ valid = true
353
+ else
354
+ valid = false
355
+ end
356
+ else
357
+ valid = false
358
+ end
359
+ else
360
+ valid = true
361
+ end
362
+ dialog.set_response_sensitive(Gtk::Dialog::RESPONSE_ACCEPT,
363
+ valid)
364
+ true
365
+ }
366
+ dialog.signal_connect('selection-changed') { |dlg, *args|
367
+ sel_proc.call(dlg.filename); false }
368
+ fmt_combo.signal_connect('changed') { |*args|
369
+ sel_proc.call(dialog.filename); false }
370
+ find_entry_proc = proc { |wgt|
371
+ if wgt.kind_of?(Gtk::Entry)
372
+ wgt
373
+ elsif wgt.kind_of?(Gtk::Container)
374
+ res = nil
375
+ wgt.children.each { |child|
376
+ break if (res = find_entry_proc.call(child))
377
+ }
378
+ res
379
+ end
380
+ }
381
+ if entry = find_entry_proc.call(dialog)
382
+ entry_mod_proc = proc { |entry, *args|
383
+ sel_proc.call(entry.text); false }
384
+ entry.signal_connect('changed', &entry_mod_proc)
385
+ end
386
+ resp = dialog.run
387
+ path = dialog.filename
388
+ fmt_active = fmt_combo.active if fmt_combo.active != 0
389
+ dialog.destroy
390
+ return if resp != Gtk::Dialog::RESPONSE_ACCEPT
391
+ if fmt_active == 1
392
+ fmt = 'txt'
393
+ else
394
+ fmt = fmts[fmt_active]
395
+ end
396
+ if FileTest.exist?(path)
397
+ if fmt != 'txt'
398
+ return unless PGtk.overwrite_dialog(path)
399
+ fmt = [pixbuf_width, pixbuf_height, fmt]
400
+ else
401
+ dialog = Gtk::Dialog.new('Output File Exists', nil,
402
+ Gtk::Dialog::MODAL,
403
+ ['_Replace', 0],
404
+ ['_Extend with new objects', 1],
405
+ [Gtk::Stock::CANCEL, 2])
406
+ hbox = Gtk::HBox.new(false, 0)
407
+ hbox.set_border_width(8)
408
+ dialog.vbox.pack_start(hbox, false, false, 0)
409
+ hbox.pack_start(Gtk::Image.new(
410
+ Gtk::Stock::DIALOG_QUESTION, Gtk::IconSize::DIALOG),
411
+ false, false, 0)
412
+ label = Gtk::Label.new
413
+ label.markup = "File <b>#{path}</b> already exists."
414
+ hbox.pack_start(label, false, false, 0)
415
+ hbox.show_all
416
+ resp = dialog.run
417
+ dialog.destroy
418
+ return if resp == 2
419
+ mode = ['w', 'a'].at(resp)
420
+ fmt = [fmt, mode]
421
+ end
422
+ else
423
+ if fmt == 'txt'
424
+ fmt = [fmt, 'w']
425
+ else
426
+ fmt = [pixbuf_width, pixbuf_height, fmt]
427
+ end
428
+ end
429
+ begin
430
+ self.write_objs(path, fmt, objs)
431
+ rescue IOError, Gdk::PixbufError
432
+ PGtk.show_exc_dialog
433
+ end
434
+ end
435
+
436
+ def initialize(times_arr=0, obj_start_i=nil, end_i=nil)
437
+ if end_i
438
+ @__under__ = SubArr.new(times_arr, obj_start_i, end_i)
439
+ elsif obj_start_i
440
+ @__under__ = Array.new(times_arr, obj_start_i)
441
+ else
442
+ @__under__ = Array.new(times_arr)
443
+ end
444
+ self.img_obj_rebuild
445
+ self.pguiobj_init(nil, OpenStruct.new('marshal_dump_btn'=>false,
446
+ 'dump_to_s_btn' => false, 'dump_inspect_btn' => false))
447
+ end
448
+
449
+ (Array.instance_methods+SubArr.instance_methods-Object.instance_methods-
450
+ ["[]=", "<<", "push", "+", "-", "*", "concat", "replace"]).
451
+ uniq!.each { |meth|
452
+ if meth[-1,1] == "="
453
+ module_eval <<-"eval_end"
454
+ def #{meth}(val)
455
+ @__under__.#{meth}(val)
456
+ end
457
+ eval_end
458
+ else
459
+ module_eval <<-"eval_end"
460
+ def #{meth}(*args, &block)
461
+ @__under__.#{meth}(*args, &block)
462
+ end
463
+ eval_end
464
+ end
465
+ }
466
+
467
+ def []=(*args, &block)
468
+ @__under__.[]=(*args, &block)
469
+ end
470
+
471
+ def replace(*args, &block)
472
+ @__under__.replace(*args, &block)
473
+ self
474
+ end
475
+
476
+ def concat(*args, &block)
477
+ @__under__.concat(*args, &block)
478
+ self
479
+ end
480
+
481
+ def <<(*args, &block)
482
+ @__under__.<<(*args, &block)
483
+ self
484
+ end
485
+
486
+ def push(*args, &block)
487
+ @__under__.push(*args, &block)
488
+ self
489
+ end
490
+
491
+ def +(*args, &block)
492
+ ImageObject.new.replace(@__under__.+(*args, &block))
493
+ end
494
+
495
+ def -(*args, &block)
496
+ ImageObject.new.replace(@__under__.-(*args, &block))
497
+ end
498
+
499
+ def *(*args, &block)
500
+ ImageObject.new.replace(@__under__.*(*args, &block))
501
+ end
502
+
503
+ def dup
504
+ ImageObject.new(@__under__.dup)
505
+ end
506
+
507
+ def img_obj_rebuild
508
+ @img_obj_min_x = @img_obj_max_x = nil
509
+ @img_obj_min_y = @img_obj_max_y = nil
510
+ @img_obj_min_ax = @img_obj_max_ax = nil
511
+ @img_obj_min_ay = @img_obj_max_ay = nil
512
+ @img_obj_yx_set = nil
513
+ @img_obj_ayx_set = nil
514
+ end
515
+
516
+ def img_obj_yx_set
517
+ return @img_obj_yx_set if @img_obj_yx_set
518
+ @img_obj_yx_set = Set.new
519
+ self.each { |pix| @img_obj_yx_set.add(pix.yx) }
520
+ @img_obj_yx_set
521
+ end
522
+
523
+ def img_obj_ayx_set
524
+ return @img_obj_ayx_set if @img_obj_ayx_set
525
+ @img_obj_ayx_set = Set.new
526
+ self.each { |pix| @img_obj_ayx_set.add(pix.a_yx) }
527
+ @img_obj_ayx_set
528
+ end
529
+
530
+ def img_obj_find_xy_rect
531
+ return if self.empty?
532
+ @img_obj_min_x = @img_obj_max_x = self.first.x
533
+ @img_obj_min_y = @img_obj_max_y = self.first.y
534
+ self.each { |pix|
535
+ if pix.x < @img_obj_min_x
536
+ @img_obj_min_x = pix.x
537
+ elsif pix.x > @img_obj_max_x
538
+ @img_obj_max_x = pix.x
539
+ end
540
+ if pix.y < @img_obj_min_y
541
+ @img_obj_min_y = pix.y
542
+ elsif pix.y > @img_obj_max_y
543
+ @img_obj_max_y = pix.y
544
+ end
545
+ }
546
+ end
547
+
548
+ def img_obj_find_axy_rect
549
+ return if self.empty?
550
+ @img_obj_min_ax = @img_obj_max_ax = self.first.ax
551
+ @img_obj_min_ay = @img_obj_max_ay = self.first.ay
552
+ self.each { |pix|
553
+ if pix.ax < @img_obj_min_ax
554
+ @img_obj_min_ax = pix.ax
555
+ elsif pix.ax > @img_obj_max_ax
556
+ @img_obj_max_ax = pix.ax
557
+ end
558
+ if pix.ay < @img_obj_min_ay
559
+ @img_obj_min_ay = pix.ay
560
+ elsif pix.ay > @img_obj_max_ay
561
+ @img_obj_max_ay = pix.ay
562
+ end
563
+ }
564
+ end
565
+
566
+ def img_obj_min_x
567
+ self.img_obj_find_xy_rect unless @img_obj_min_x
568
+ @img_obj_min_x
569
+ end
570
+
571
+ def img_obj_max_x
572
+ self.img_obj_find_xy_rect unless @img_obj_max_x
573
+ @img_obj_max_x
574
+ end
575
+
576
+ def img_obj_min_y
577
+ self.img_obj_find_xy_rect unless @img_obj_min_y
578
+ @img_obj_min_y
579
+ end
580
+
581
+ def img_obj_max_y
582
+ self.img_obj_find_xy_rect unless @img_obj_max_y
583
+ @img_obj_max_y
584
+ end
585
+
586
+ def img_obj_min_ax
587
+ self.img_obj_find_axy_rect unless @img_obj_min_ax
588
+ @img_obj_min_ax
589
+ end
590
+
591
+ def img_obj_max_ax
592
+ self.img_obj_find_axy_rect unless @img_obj_max_ax
593
+ @img_obj_max_ax
594
+ end
595
+
596
+ def img_obj_min_ay
597
+ self.img_obj_find_axy_rect unless @img_obj_min_ay
598
+ @img_obj_min_ay
599
+ end
600
+
601
+ def img_obj_max_ay
602
+ self.img_obj_find_axy_rect unless @img_obj_max_ay
603
+ @img_obj_max_ay
604
+ end
605
+
606
+ def img_obj_freeze
607
+ @__under__.freeze
608
+ end
609
+
610
+ def opt_spanning_tree(min, mk_conn, get_conns)
611
+ return if self.empty?
612
+ # Start from a node pixel:
613
+ return if (conns = get_conns.call(self.first)).empty?
614
+ #$PDbgLog.sig_call(self)
615
+ pix = conns[0].last
616
+ spanned = {pix.yx => true}
617
+ active_conns = min ? PMinHeap.new{|cn1,cn2| cn1[3] <=> cn2[3]} :
618
+ PMinHeap.new { |cn1, cn2| cn2[3] <=> cn1[3] }
619
+ get_conns.call(pix).each_with_index { |conn, conn_i|
620
+ active_conns.push([pix, conn.last, conn_i, conn.length]) }
621
+ cn = nil
622
+ loop do
623
+ # $PDbgLog.print_msg "#{spanned.length}/#{self.length
624
+ # }; spanned: #{PixbufPix.yx_path_to_s(spanned.keys.sort
625
+ # )}; active_conns: #{active_conns.collect{|frm|
626
+ # frm[0].coords_to_s + "--" + frm[1].coords_to_s +
627
+ # ",#{frm[2]}:#{frm[3]}"}.join("; ")}. "
628
+ loop do
629
+ unless (cn = active_conns.pop)
630
+ #$PDbgLog.sig_return
631
+ return
632
+ end
633
+ break unless spanned.include?(cn[1].yx)
634
+ end
635
+ #$PDbgLog.puts_msg "Calling mk_conn(#{cn[0].coords_to_s
636
+ # }, #{cn[2]})"
637
+ mk_conn.call(cn[0], cn[2])
638
+ spanned[cn[1].yx] = true
639
+ get_conns.call(cn[1]).each_with_index { |conn, conn_i|
640
+ next if spanned.include?(conn.last.yx)
641
+ active_conns.push([cn[1], conn.last, conn_i,
642
+ conn.length])
643
+ }
644
+ end
645
+ #$PDbgLog.sig_return
646
+ end
647
+
648
+ def self.img_obj_add_meths(*meths)
649
+ #$PDbgLog.sig_call(self)
650
+ #$PDbgLog.puts_msg "meths: #{meths.inspect}"
651
+ PGuiObj::MObj.pguiobj_add_methods_to(self, *meths)
652
+ #$PDbgLog.sig_return
653
+ end
654
+ end
655
+
656
+ class ImageObjectPixCalc
657
+ attr_reader :pix, :path_cache, :first_path_cache, :get_pix_proc
658
+
659
+ def initialize(pix, &get_pix_proc)
660
+ @pix = pix
661
+ @path_cache = {}
662
+ @first_path_cache = {}
663
+ @get_pix_proc = get_pix_proc
664
+ end
665
+
666
+ def find_shortest_pix_path_to_pix(dest, levs_left=-1,
667
+ path_cache=@path_cache, &get_neighbs)
668
+ #$PDbgLog.sig_call(self)
669
+ path_cache = {} unless path_cache
670
+ tail = [[@pix, 0]]
671
+ path_cache[@pix.a_yx]=0 unless path_cache.include?(@pix.a_yx) &&
672
+ path_cache[@pix.a_yx] <= 0
673
+ #$PDbgLog.print_msg "dest=#{dest}, from #{
674
+ # @pix.coords_to_s}, levs_left=#{levs_left}: "
675
+ if levs_left == 0
676
+ #$PDbgLog.sig_return("levs_left==0: nil")
677
+ return nil
678
+ end
679
+ while !tail.empty?
680
+ pix, lev = *tail.shift
681
+ if path_cache.include?(dest.a_yx)
682
+ res = []; pix = dest
683
+ i = path_cache[pix.a_yx]
684
+ while i > 0
685
+ res[i-=1] = pix
686
+ yield(pix).each { |pix|
687
+ break if path_cache[pix.a_yx]==i
688
+ }
689
+ end
690
+ #$PDbgLog.sig_return(PixbufPix.path_to_s(res))
691
+ return res
692
+ end
693
+ yield(pix).each { |neighb|
694
+ unless (path_cache.include?(neighb.a_yx) &&
695
+ path_cache[neighb.a_yx] <= lev+1) ||
696
+ lev+1 == levs_left
697
+ tail.push([neighb, lev+1])
698
+ path_cache[neighb.a_yx] = lev+1
699
+ end
700
+ }
701
+ end
702
+ #$PDbgLog.sig_return("nil")
703
+ nil
704
+ end
705
+
706
+ def find_shortest_path_pix_to(dest, levs_left=-1, &get_neighbs)
707
+ #$PDbgLog.sig_call(self)
708
+ if dest.kind_of?(Proc)
709
+ dest_proc = dest
710
+ else
711
+ #$PDbgLog.sig_return
712
+ return self.find_shortest_pix_path_to_pix(dest,
713
+ levs_left, {}, &get_neighbs)
714
+ end
715
+ path_cache = { @pix.a_yx => 0 }
716
+ tail = [[@pix, 0]]
717
+ #$PDbgLog.print_msg "dest=#{dest}, from #{
718
+ # @pix.coords_to_s}, levs_left=#{levs_left}: "
719
+ if levs_left == 0
720
+ #$PDbgLog.sig_return("levs_left==0: nil")
721
+ return nil
722
+ end
723
+ while !tail.empty?
724
+ pix, lev = *tail.shift
725
+ #if lev > 100
726
+ #$PDbgLog.print_msg
727
+ #puts "dest=#{dest}, from #{
728
+ # @pix.coords_to_s}, levs_left=#{levs_left}: #{tail.
729
+ # length},#{pix.coords_to_s},#{lev}; "
730
+ #end
731
+ # $PDbgLog.print_msg "#{tail.length},#{pix.coords_to_s},#{
732
+ # lev}; "
733
+ if dest_proc.call(pix)
734
+ res = []
735
+ i = path_cache[pix.a_yx]
736
+ while i > 0
737
+ res[i-=1] = pix
738
+ yield(pix).each { |pix|
739
+ break if path_cache[pix.a_yx]==i
740
+ }
741
+ end
742
+ #$PDbgLog.sig_return(PixbufPix.path_to_s(res))
743
+ return res
744
+ end
745
+ yield(pix).each { |neighb|
746
+ unless (path_cache.include?(neighb.a_yx) &&
747
+ path_cache[neighb.a_yx] <= lev+1) ||
748
+ lev+1 == levs_left
749
+ tail.push([neighb, lev+1])
750
+ path_cache[neighb.a_yx] = lev+1
751
+ end
752
+ }
753
+ end
754
+ #$PDbgLog.sig_return("nil")
755
+ nil
756
+ end
757
+
758
+ def self.path_cache_to_s(path_cache)
759
+ "{#{path_cache.keys.to_a.sort.collect{|k| k.inspect + "=>[" +
760
+ (path_cache[k][0] ? path_cache[k][0].coords_to_s : 'nil'
761
+ )+"], #{path_cache[k][1]}"}.join(", ")}}"
762
+ end
763
+
764
+ def self.first_path_cache_get_path(pix, path_cache)
765
+ frm = path_cache[pix.yx]
766
+ res = [pix]
767
+ while frm[0]
768
+ res << frm[0]
769
+ frm = path_cache[frm[0].yx]
770
+ end
771
+ res.reverse!
772
+ end
773
+
774
+ def self.first_path_cache_get_path_to_self(pix, path_cache)
775
+ frm = path_cache[pix.yx]
776
+ res = [pix]
777
+ while frm[0].yx != @pix.yx
778
+ res << frm[0]
779
+ frm = path_cache[frm[0].yx]
780
+ end
781
+ res << frm[0]
782
+ res.reverse!
783
+ end
784
+
785
+ def self.first_path_cache_get_ayx_path(pix, path_cache)
786
+ #$PDbgLog.sig_call(self)
787
+ #$PDbgLog.print_msg "pix#{pix.coords_to_s} path_cache: #{self.
788
+ # path_cache_to_s(path_cache)}: "
789
+ frm = path_cache[pix.a_yx]
790
+ res = [pix]
791
+ while frm[0]
792
+ #$PDbgLog.print_msg "#{frm[0].a_yx.inspect} "
793
+ res << frm[0]
794
+ frm = path_cache[frm[0].a_yx]
795
+ end
796
+ #$PDbgLog.sig_return
797
+ res.reverse!
798
+ end
799
+
800
+ def find_first_path_to(dest, max_lev=1.0/0.0, path_cache=nil,
801
+ &get_neighbs_levs)
802
+ if dest.kind_of?(Proc)
803
+ dest_proc = dest
804
+ else
805
+ dest_proc = proc {|px,lev| dest.a_eql?(px)}
806
+ end
807
+ tail = PMinHeap.new { |frm1,frm2| frm1[1] <=> frm2[1] }
808
+ unless path_cache
809
+ path_cache = @first_path_cache
810
+ unless dest.kind_of?(Proc)
811
+ return ImageObjectPixCalc.
812
+ first_path_cache_get_ayx_path(dest, path_cache) if
813
+ path_cache.include?(dest.a_yx)
814
+ end
815
+ path_cache.each_pair { |pix, frm|
816
+ tail.push([@get_pix_proc.call(pix[1], pix[0]),
817
+ frm[1]])
818
+ }
819
+ end
820
+ #$PDbgLog.sig_call(self)
821
+ path_cache[@pix.a_yx] = [nil, 0]
822
+ tail.push([@pix, 0])
823
+ if max_lev < 1
824
+ #$PDbgLog.sig_return("max_lev < 1: nil")
825
+ return nil
826
+ end
827
+ while !tail.empty?
828
+ #$PDbgLog.puts_msg "tail: " + tail.collect { |frm|
829
+ # (frm[0] ? frm[0].coords_to_s : frm[0].inspect) +
830
+ # ":#{frm[1]}" }.join(" ")
831
+ pix, lev = *tail.pop
832
+ #$PDbgLog.puts_msg "path_cache: #{ImageObjectPixCalc.
833
+ # path_cache_to_s(path_cache)}"
834
+ #$PDbgLog.print_msg pix.coords_to_s + ",#{lev}"
835
+ #$PDbgLog.print_msg "<-#{path_cache[pix.a_yx][0] ?
836
+ # path_cache[pix.a_yx][0].coords_to_s :
837
+ # path_cache[pix.a_yx][0].inspect} "
838
+ next if path_cache.include?(pix.a_yx) &&
839
+ path_cache[pix.a_yx][1] < lev
840
+ if dest_proc.call(pix, lev)
841
+ res = ImageObjectPixCalc.
842
+ first_path_cache_get_ayx_path(pix, path_cache)
843
+ #$PDbgLog.sig_return(PixbufPix.path_to_s(res))
844
+ return res
845
+ end
846
+ yield(pix, lev).each { |args| neighb, neighb_lev = *args
847
+ unless (path_cache.include?(neighb.a_yx) &&
848
+ path_cache[neighb.a_yx][1] <= neighb_lev) ||
849
+ neighb_lev > max_lev
850
+ tail.push([neighb, neighb_lev])
851
+ path_cache[neighb.a_yx]=[pix,neighb_lev]
852
+ end
853
+ }
854
+ end
855
+ #$PDbgLog.sig_return("nil")
856
+ nil
857
+ end
858
+
859
+ def kill_path_cache!
860
+ @path_cache.clear
861
+ @first_path_cache.clear
862
+ end
863
+ end
864
+
865
+ end