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 '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