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,751 @@
1
+ require 'set'
2
+ require 'pav/pix'
3
+ require 'pav/heap'
4
+
5
+ module PPix
6
+
7
+ module MPixbufPix
8
+ def img_obj_subpix8(sub_n)
9
+ # @img_obj_subpix8 = [] unless @img_obj_subpix8
10
+ # tmp = @img_obj_subpix8[sub_n]
11
+ # return tmp if tmp
12
+ #$PDbgLog.sig_call(self)
13
+ #$PDbgLog.puts_msg self.coords_to_s + ", sub_n=#{sub_n}"
14
+ #res =
15
+ #@img_obj_subpix8[sub_n] =
16
+ ImageObjectSubpix.new(Subpix8.new(self, sub_n))
17
+ #$PDbgLog.puts_msg res.inspect
18
+ #$PDbgLog.sig_return
19
+ #res
20
+ end
21
+
22
+ def connections(&get_neighbs)
23
+ #$PDbgLog.sig_call(self)
24
+ #$PDbgLog.print_msg(self.coords_to_s)
25
+ res = []
26
+ visited = {}
27
+ for neighb in yield(self)
28
+ #$PDbgLog.print_msg " neighb#{neighb.coords_to_s}: "
29
+ next if visited.include?(neighb.a_yx)
30
+ res << [tmp_pix=neighb]
31
+ prev_pix = self
32
+ while (pix_ngbs = yield(tmp_pix)).length == 2
33
+ if pix_ngbs.first.a_eql?(prev_pix)
34
+ prev_pix = tmp_pix
35
+ tmp_pix = pix_ngbs.last
36
+ else
37
+ prev_pix = tmp_pix
38
+ tmp_pix = pix_ngbs.first
39
+ end
40
+ res.last << tmp_pix
41
+ if self.a_eql?(tmp_pix)
42
+ visited[prev_pix.a_yx] = true
43
+ break
44
+ end
45
+ end
46
+ #$PDbgLog.puts_msg "."
47
+ end
48
+ #$PDbgLog.sig_return
49
+ res
50
+ end
51
+
52
+ def rev_conn_idx(conns, conn_i, rev_conns)
53
+ #$PDbgLog.sig_call(self)
54
+ #$PDbgLog.puts_msg "(#{conn_i}) from (#{self.x}, #{self.y})."
55
+ path = conns[conn_i]
56
+ #$PDbgLog.puts_msg "path: #{PixbufPix.path_to_s(path)}"
57
+ end_pix = path.last
58
+ if self.a_eql?(end_pix)
59
+ return conn_i
60
+ else
61
+ path = path.reverse[1, path.length-1] << self
62
+ #$PDbgLog.puts_msg "rev_path: #{
63
+ # PixbufPix.path_to_s(path)}"
64
+ rev_conns.each_with_index { |rev_conn, i|
65
+ #$PDbgLog.puts_msg "rev_conn: #{
66
+ # PixbufPix.path_to_s(rev_conn)}"
67
+ if PixbufPix.a_paths_eql?(path, rev_conn)
68
+ return i
69
+ end
70
+ }
71
+ end
72
+ #$PDbgLog.sig_return
73
+ nil
74
+ end
75
+
76
+ def find_shortest_pix_path_to(dest, levs_left=-1, &get_neighbs)
77
+ #$PDbgLog.sig_call(self)
78
+ if dest.kind_of?(Proc)
79
+ dest_proc = dest
80
+ else
81
+ dest_proc = proc { |px| px.y==dest.y && px.x==dest.x }
82
+ end
83
+ path_cache = { self.yx => 0 }
84
+ tail = [[self, 0]]
85
+ #$PDbgLog.print_msg "dest=#{dest}, from #{
86
+ # self.coords_to_s}, levs_left=#{levs_left}: "
87
+ if levs_left == 0
88
+ #$PDbgLog.sig_return("levs_left==0: nil")
89
+ return nil
90
+ end
91
+ while !tail.empty?
92
+ pix, lev = *tail.shift
93
+ #if lev > 100
94
+ #$PDbgLog.print_msg
95
+ #puts "dest=#{dest}, from #{
96
+ # self.coords_to_s}, levs_left=#{levs_left}: #{tail.
97
+ # length},#{pix.coords_to_s},#{lev}; "
98
+ #end
99
+ # $PDbgLog.print_msg "#{tail.length},#{pix.coords_to_s},#{
100
+ # lev}; "
101
+ if dest_proc.call(pix)
102
+ res = []
103
+ i = path_cache[pix.yx]
104
+ while i > 0
105
+ res[i-=1] = pix
106
+ yield(pix).each { |pix|
107
+ break if path_cache[pix.yx] == i
108
+ }
109
+ end
110
+ #$PDbgLog.sig_return(PixbufPix.path_to_s(res))
111
+ return res
112
+ end
113
+ yield(pix).each { |neighb|
114
+ unless (path_cache.include?(neighb.yx) &&
115
+ path_cache[neighb.yx] <= lev+1) ||
116
+ lev+1 == levs_left
117
+ tail.push([neighb, lev+1])
118
+ path_cache[neighb.yx] = lev+1
119
+ end
120
+ }
121
+ end
122
+ #$PDbgLog.sig_return("nil")
123
+ nil
124
+ end
125
+
126
+ def find_shortest_pix_path_into(res, dest, levs_left=-1, path_cache={},
127
+ tail=[], neighbs=[]) # &get_neighbs
128
+ #$PDbgLog.sig_call(self)
129
+ if dest.kind_of?(Proc)
130
+ dest_proc = dest
131
+ else
132
+ dest_proc = proc { |px| px.y==dest.y && px.x==dest.x }
133
+ end
134
+ path_cache.clear; path_cache[self.yx] = 0
135
+ tail.clear; tail << self << 0
136
+ #$PDbgLog.print_msg "dest=#{dest}, from #{
137
+ # self.coords_to_s}, levs_left=#{levs_left}: "
138
+ if levs_left == 0
139
+ #$PDbgLog.sig_return("levs_left==0: nil")
140
+ return nil
141
+ end
142
+ while !tail.empty?
143
+ pix = tail.shift; lev = tail.shift
144
+ #if lev > 100
145
+ #$PDbgLog.print_msg
146
+ #puts "dest=#{dest}, from #{
147
+ # self.coords_to_s}, levs_left=#{levs_left}: #{tail.
148
+ # length},#{pix.coords_to_s},#{lev}; "
149
+ #end
150
+ # $PDbgLog.print_msg "#{tail.length},#{pix.coords_to_s},#{
151
+ # lev}; "
152
+ if dest_proc.call(pix)
153
+ res.clear
154
+ i = path_cache[pix.yx]
155
+ while i > 0
156
+ res[i-=1] = pix
157
+ yield(pix, neighbs).each { |pix|
158
+ break if path_cache[pix.yx] == i
159
+ }
160
+ end
161
+ #$PDbgLog.sig_return(PixbufPix.path_to_s(res))
162
+ return res
163
+ end
164
+ yield(pix, neighbs).each { |neighb|
165
+ unless (path_cache.include?(neighb.yx) &&
166
+ path_cache[neighb.yx] <= lev+1) ||
167
+ lev+1 == levs_left
168
+ tail << neighb << (lev+1)
169
+ path_cache[neighb.yx] = lev+1
170
+ end
171
+ }
172
+ end
173
+ #$PDbgLog.sig_return("nil")
174
+ nil
175
+ end
176
+
177
+ def find_first_path_to(dest, max_lev=1.0/0.0, &get_neighbs_levs)
178
+ $PDbgLog.sig_call(self)
179
+ if dest.kind_of?(Proc)
180
+ dest_proc = dest
181
+ else
182
+ dest_proc = proc { |px| dest.a_eql?(px) }
183
+ end
184
+ path_cache = { self.a_yx => [nil, 0] }
185
+ tail = PMinHeap.new { |frm1,frm2| frm1[1] <=> frm2[1] }
186
+ tail.push([self, 0])
187
+ if max_lev < 1
188
+ $PDbgLog.sig_return("max_lev < 1: nil")
189
+ return nil
190
+ end
191
+ while !tail.empty?
192
+ pix, lev = *tail.pop
193
+ if dest_proc.call(pix, lev)
194
+ frm = path_cache[pix.a_yx]
195
+ res = [pix]
196
+ while frm[0]
197
+ res << frm[0]
198
+ frm = path_cache[frm[0].a_yx]
199
+ end
200
+ $PDbgLog.sig_return(PixbufPix.path_to_s(
201
+ res.reverse))
202
+ return res.reverse!
203
+ end
204
+ yield(pix, lev).each { |args| neighb, neighb_lev = *args
205
+ unless (path_cache.include?(neighb.a_yx) &&
206
+ path_cache[neighb.a_yx][1] <= neighb_lev) ||
207
+ neighb_lev > max_lev
208
+ tail.push([neighb, neighb_lev])
209
+ path_cache[neighb.a_yx]=[pix,neighb_lev]
210
+ end
211
+ }
212
+ end
213
+ $PDbgLog.sig_return("nil")
214
+ nil
215
+ end
216
+
217
+ def inspect
218
+ idmem = self.object_id & ( (1 << (8*self.object_id.size)) - 1 )
219
+ "<#{self.class.name}:0x%x #{self.coords_to_s}" % idmem +
220
+ "#{self.instance_variables.collect { |var| " " + var + "=" +
221
+ self.instance_variable_get(var).inspect }.join(",")}>"
222
+ end
223
+ end
224
+
225
+ class ImageObjectSubpix #< ImageObjectPix
226
+ attr_reader :subpix, :ppix
227
+
228
+ def initialize(subpix)
229
+ @subpix = subpix
230
+ super(subpix.img_pix)
231
+ @ppix = ppix
232
+ end
233
+
234
+ def method_missing(id, *args, &block)
235
+ begin
236
+ @subpix.send(id, *args, &block)
237
+ rescue NoMethodError
238
+ @subpix.img_pix.send(id, *args, &block)
239
+ end
240
+ end
241
+
242
+ def to_s
243
+ @subpix.to_s
244
+ end
245
+
246
+ def inspect
247
+ idmem = self.object_id & ( (1 << (8*self.object_id.size)) - 1 )
248
+ "<#{self.class.name}:0x%x @subpix#{@subpix.to_s}"%idmem +
249
+ "#{self.instance_variables.collect{|var|"#{var}=#{self.
250
+ instance_variable_get(var).inspect}"}.join(",")}>" #"
251
+ end
252
+ end
253
+
254
+ class ImageObject
255
+ @img_obj_meths = []
256
+
257
+ def initialize(times_arr=0, obj_start_i=nil, end_i=nil)
258
+ if end_i
259
+ @__under__ = SubArr.new(times_arr, obj_start_i, end_i)
260
+ elsif obj_start_i
261
+ @__under__ = Array.new(times_arr, obj_start_i)
262
+ else
263
+ @__under__ = Array.new(times_arr)
264
+ end
265
+ self.img_obj_rebuild
266
+ end
267
+
268
+ (Array.instance_methods+SubArr.instance_methods-Object.instance_methods-
269
+ ["[]=", "<<", "push", "+", "-", "*", "concat", "replace"]).
270
+ uniq!.each { |meth|
271
+ if meth[-1,1] == "="
272
+ module_eval <<-"eval_end"
273
+ def #{meth}(val)
274
+ @__under__.#{meth}(val)
275
+ end
276
+ eval_end
277
+ else
278
+ module_eval <<-"eval_end"
279
+ def #{meth}(*args, &block)
280
+ @__under__.#{meth}(*args, &block)
281
+ end
282
+ eval_end
283
+ end
284
+ }
285
+
286
+ def []=(*args, &block)
287
+ @__under__.[]=(*args, &block)
288
+ end
289
+
290
+ def replace(*args, &block)
291
+ @__under__.replace(*args, &block)
292
+ self
293
+ end
294
+
295
+ def concat(*args, &block)
296
+ @__under__.concat(*args, &block)
297
+ self
298
+ end
299
+
300
+ def <<(*args, &block)
301
+ @__under__.<<(*args, &block)
302
+ self
303
+ end
304
+
305
+ def push(*args, &block)
306
+ @__under__.push(*args, &block)
307
+ self
308
+ end
309
+
310
+ def +(*args, &block)
311
+ ImageObject.new.replace(@__under__.+(*args, &block))
312
+ end
313
+
314
+ def -(*args, &block)
315
+ ImageObject.new.replace(@__under__.-(*args, &block))
316
+ end
317
+
318
+ def *(*args, &block)
319
+ ImageObject.new.replace(@__under__.*(*args, &block))
320
+ end
321
+
322
+ def dup
323
+ ImageObject.new(@__under__.dup)
324
+ end
325
+
326
+ def self.img_obj_sub_obj_meths
327
+ @img_obj_sub_obj_meths
328
+ end
329
+
330
+ def self.get_img_obj_sub_obj_meths
331
+ return @img_obj_sub_obj_meths if @img_obj_sub_obj_meths
332
+ begin
333
+ return (@img_obj_sub_obj_meths=@img_obj_sub_obj_meths.dup) if
334
+ (@img_obj_sub_obj_meths =
335
+ self.superclass.get_img_obj_sub_obj_meths)
336
+ rescue NoMethodError
337
+ end
338
+ @img_obj_sub_obj_meths = []
339
+ end
340
+
341
+ def self.img_obj_add_sub_obj(*args)
342
+ self.get_img_obj_sub_obj_meths.concat(args.collect{|m| m.to_s})
343
+ end
344
+
345
+ def self.img_obj_add_to_sub_objs(*args)
346
+ return unless @img_obj_sub_obj_meths
347
+ @img_obj_sub_obj_meths.concat(args.collect{|m| m.to_s})
348
+ end
349
+
350
+ def img_obj_possible_sub_obj_meths
351
+ (self.public_methods - Object.instance_methods -
352
+ Array.instance_methods - SubArr.instance_methods -
353
+ ["rewind", "rebuild", "get_sub_img_objs"]).delete_if { |meth|
354
+ meth.starts_with("_") || meth.starts_with("delete_") ||
355
+ ![-1, 0].include?(self.method(meth).arity)
356
+ }
357
+ end
358
+
359
+ def get_sub_img_objs(excl_set={})
360
+ #$PDbgLog.sig_call(self)
361
+ #$PDbgLog.print_msg self.inspect
362
+ objs = {}
363
+ if (meths = self.class.img_obj_sub_obj_meths)
364
+ meths.each { |meth|
365
+ res = self.send(meth)
366
+ next if excl_set.include?(res.object_id)
367
+ objs[meth] = res
368
+ excl_set[res.object_id] = true
369
+ }
370
+ #$PDbgLog.sig_return
371
+ return objs
372
+ end
373
+ self.img_obj_possible_sub_obj_meths.each { |meth|
374
+ res = self.send(meth)
375
+ #$PDbgLog.print_msg "meth=#{meth}:%x " % res.object_id
376
+ next if excl_set.include?(res.object_id)
377
+ if res.kind_of?(ImageObject)
378
+ objs[meth] = res
379
+ excl_set[res.object_id] = true
380
+ elsif res.kind_of?(Array) && !res.empty? &&
381
+ res.first.kind_of?(ImageObject)
382
+ objs[meth] = res
383
+ excl_set[res.object_id] = true
384
+ elsif res.kind_of?(Hash) && !res.empty?
385
+ flag = true
386
+ res.each_value { |v|
387
+ flag = v.kind_of?(ImageObject)
388
+ break
389
+ }
390
+ if flag
391
+ objs[meth] = res
392
+ excl_set[res.object_id] = true
393
+ end
394
+ end
395
+ }
396
+ #$PDbgLog.sig_return
397
+ objs
398
+ end
399
+
400
+ def img_obj_rebuild
401
+ @img_obj_min_x = @img_obj_max_x = nil
402
+ @img_obj_min_y = @img_obj_max_y = nil
403
+ @img_obj_min_ax = @img_obj_max_ax = nil
404
+ @img_obj_min_ay = @img_obj_max_ay = nil
405
+ @img_obj_yx_set = nil
406
+ @img_obj_ayx_set = nil
407
+ end
408
+
409
+ def img_obj_yx_set
410
+ return @img_obj_yx_set if @img_obj_yx_set
411
+ @img_obj_yx_set = Set.new
412
+ self.each { |pix| @img_obj_yx_set.add(pix.yx) }
413
+ @img_obj_yx_set
414
+ end
415
+
416
+ def img_obj_ayx_set
417
+ return @img_obj_ayx_set if @img_obj_ayx_set
418
+ @img_obj_ayx_set = Set.new
419
+ self.each { |pix| @img_obj_ayx_set.add(pix.a_yx) }
420
+ @img_obj_ayx_set
421
+ end
422
+
423
+ def img_obj_find_xy_rect
424
+ return if self.empty?
425
+ @img_obj_min_x = @img_obj_max_x = self.first.x
426
+ @img_obj_min_y = @img_obj_max_y = self.first.y
427
+ self.each { |pix|
428
+ if pix.x < @img_obj_min_x
429
+ @img_obj_min_x = pix.x
430
+ elsif pix.x > @img_obj_max_x
431
+ @img_obj_max_x = pix.x
432
+ end
433
+ if pix.y < @img_obj_min_y
434
+ @img_obj_min_y = pix.y
435
+ elsif pix.y > @img_obj_max_y
436
+ @img_obj_max_y = pix.y
437
+ end
438
+ }
439
+ end
440
+
441
+ def img_obj_find_axy_rect
442
+ return if self.empty?
443
+ @img_obj_min_ax = @img_obj_max_ax = self.first.ax
444
+ @img_obj_min_ay = @img_obj_max_ay = self.first.ay
445
+ self.each { |pix|
446
+ if pix.ax < @img_obj_min_ax
447
+ @img_obj_min_ax = pix.ax
448
+ elsif pix.ax > @img_obj_max_ax
449
+ @img_obj_max_ax = pix.ax
450
+ end
451
+ if pix.ay < @img_obj_min_ay
452
+ @img_obj_min_ay = pix.ay
453
+ elsif pix.ay > @img_obj_max_ay
454
+ @img_obj_max_ay = pix.ay
455
+ end
456
+ }
457
+ end
458
+
459
+ def img_obj_min_x
460
+ self.img_obj_find_xy_rect unless @img_obj_min_x
461
+ @img_obj_min_x
462
+ end
463
+
464
+ def img_obj_max_x
465
+ self.img_obj_find_xy_rect unless @img_obj_max_x
466
+ @img_obj_max_x
467
+ end
468
+
469
+ def img_obj_min_y
470
+ self.img_obj_find_xy_rect unless @img_obj_min_y
471
+ @img_obj_min_y
472
+ end
473
+
474
+ def img_obj_max_y
475
+ self.img_obj_find_xy_rect unless @img_obj_max_y
476
+ @img_obj_max_y
477
+ end
478
+
479
+ def img_obj_min_ax
480
+ self.img_obj_find_axy_rect unless @img_obj_min_ax
481
+ @img_obj_min_ax
482
+ end
483
+
484
+ def img_obj_max_ax
485
+ self.img_obj_find_axy_rect unless @img_obj_max_ax
486
+ @img_obj_max_ax
487
+ end
488
+
489
+ def img_obj_min_ay
490
+ self.img_obj_find_axy_rect unless @img_obj_min_ay
491
+ @img_obj_min_ay
492
+ end
493
+
494
+ def img_obj_max_ay
495
+ self.img_obj_find_axy_rect unless @img_obj_max_ay
496
+ @img_obj_max_ay
497
+ end
498
+
499
+ def img_obj_freeze
500
+ @__under__.freeze
501
+ end
502
+
503
+ def opt_spanning_tree(min, mk_conn, get_conns)
504
+ return if self.empty?
505
+ # Start from a node pixel:
506
+ return if (conns = get_conns.call(self.first)).empty?
507
+ #$PDbgLog.sig_call(self)
508
+ pix = conns[0].last
509
+ spanned = {pix.yx => true}
510
+ active_conns = min ? PMinHeap.new{|cn1,cn2| cn1[3] <=> cn2[3]} :
511
+ PMinHeap.new { |cn1, cn2| cn2[3] <=> cn1[3] }
512
+ get_conns.call(pix).each_with_index { |conn, conn_i|
513
+ active_conns.push([pix, conn.last, conn_i, conn.length]) }
514
+ cn = nil
515
+ loop do
516
+ # $PDbgLog.print_msg "#{spanned.length}/#{self.length
517
+ # }; spanned: #{PixbufPix.yx_path_to_s(spanned.keys.sort
518
+ # )}; active_conns: #{active_conns.collect{|frm|
519
+ # frm[0].coords_to_s + "--" + frm[1].coords_to_s +
520
+ # ",#{frm[2]}:#{frm[3]}"}.join("; ")}. "
521
+ loop do
522
+ unless (cn = active_conns.pop)
523
+ #$PDbgLog.sig_return
524
+ return
525
+ end
526
+ break unless spanned.include?(cn[1].yx)
527
+ end
528
+ #$PDbgLog.puts_msg "Calling mk_conn(#{cn[0].coords_to_s
529
+ # }, #{cn[2]})"
530
+ mk_conn.call(cn[0], cn[2])
531
+ spanned[cn[1].yx] = true
532
+ get_conns.call(cn[1]).each_with_index { |conn, conn_i|
533
+ next if spanned.include?(conn.last.yx)
534
+ active_conns.push([cn[1], conn.last, conn_i,
535
+ conn.length])
536
+ }
537
+ end
538
+ #$PDbgLog.sig_return
539
+ end
540
+ end
541
+
542
+ class ImageObjectPixCalc
543
+ attr_reader :pix, :path_cache, :first_path_cache, :get_pix_proc
544
+
545
+ def initialize(pix, &get_pix_proc)
546
+ @pix = pix
547
+ @path_cache = {}
548
+ @first_path_cache = {}
549
+ @get_pix_proc = get_pix_proc
550
+ end
551
+
552
+ def find_shortest_pix_path_to_pix(dest, levs_left=-1,
553
+ path_cache=@path_cache, &get_neighbs)
554
+ #$PDbgLog.sig_call(self)
555
+ path_cache = {} unless path_cache
556
+ tail = [[@pix, 0]]
557
+ path_cache[@pix.a_yx]=0 unless path_cache.include?(@pix.a_yx) &&
558
+ path_cache[@pix.a_yx] <= 0
559
+ #$PDbgLog.print_msg "dest=#{dest}, from #{
560
+ # @pix.coords_to_s}, levs_left=#{levs_left}: "
561
+ if levs_left == 0
562
+ #$PDbgLog.sig_return("levs_left==0: nil")
563
+ return nil
564
+ end
565
+ while !tail.empty?
566
+ pix, lev = *tail.shift
567
+ if path_cache.include?(dest.a_yx)
568
+ res = []; pix = dest
569
+ i = path_cache[pix.a_yx]
570
+ while i > 0
571
+ res[i-=1] = pix
572
+ yield(pix).each { |pix|
573
+ break if path_cache[pix.a_yx]==i
574
+ }
575
+ end
576
+ #$PDbgLog.sig_return(PixbufPix.path_to_s(res))
577
+ return res
578
+ end
579
+ yield(pix).each { |neighb|
580
+ unless (path_cache.include?(neighb.a_yx) &&
581
+ path_cache[neighb.a_yx] <= lev+1) ||
582
+ lev+1 == levs_left
583
+ tail.push([neighb, lev+1])
584
+ path_cache[neighb.a_yx] = lev+1
585
+ end
586
+ }
587
+ end
588
+ #$PDbgLog.sig_return("nil")
589
+ nil
590
+ end
591
+
592
+ def find_shortest_path_pix_to(dest, levs_left=-1, &get_neighbs)
593
+ #$PDbgLog.sig_call(self)
594
+ if dest.kind_of?(Proc)
595
+ dest_proc = dest
596
+ else
597
+ #$PDbgLog.sig_return
598
+ return self.find_shortest_pix_path_to_pix(dest,
599
+ levs_left, {}, &get_neighbs)
600
+ end
601
+ path_cache = { @pix.a_yx => 0 }
602
+ tail = [[@pix, 0]]
603
+ #$PDbgLog.print_msg "dest=#{dest}, from #{
604
+ # @pix.coords_to_s}, levs_left=#{levs_left}: "
605
+ if levs_left == 0
606
+ #$PDbgLog.sig_return("levs_left==0: nil")
607
+ return nil
608
+ end
609
+ while !tail.empty?
610
+ pix, lev = *tail.shift
611
+ #if lev > 100
612
+ #$PDbgLog.print_msg
613
+ #puts "dest=#{dest}, from #{
614
+ # @pix.coords_to_s}, levs_left=#{levs_left}: #{tail.
615
+ # length},#{pix.coords_to_s},#{lev}; "
616
+ #end
617
+ # $PDbgLog.print_msg "#{tail.length},#{pix.coords_to_s},#{
618
+ # lev}; "
619
+ if dest_proc.call(pix)
620
+ res = []
621
+ i = path_cache[pix.a_yx]
622
+ while i > 0
623
+ res[i-=1] = pix
624
+ yield(pix).each { |pix|
625
+ break if path_cache[pix.a_yx]==i
626
+ }
627
+ end
628
+ #$PDbgLog.sig_return(PixbufPix.path_to_s(res))
629
+ return res
630
+ end
631
+ yield(pix).each { |neighb|
632
+ unless (path_cache.include?(neighb.a_yx) &&
633
+ path_cache[neighb.a_yx] <= lev+1) ||
634
+ lev+1 == levs_left
635
+ tail.push([neighb, lev+1])
636
+ path_cache[neighb.a_yx] = lev+1
637
+ end
638
+ }
639
+ end
640
+ #$PDbgLog.sig_return("nil")
641
+ nil
642
+ end
643
+
644
+ def self.path_cache_to_s(path_cache)
645
+ "{#{path_cache.keys.to_a.sort.collect{|k| k.inspect + "=>[" +
646
+ (path_cache[k][0] ? path_cache[k][0].coords_to_s : 'nil'
647
+ )+"], #{path_cache[k][1]}"}.join(", ")}}"
648
+ end
649
+
650
+ def self.first_path_cache_get_path(pix, path_cache)
651
+ frm = path_cache[pix.yx]
652
+ res = [pix]
653
+ while frm[0]
654
+ res << frm[0]
655
+ frm = path_cache[frm[0].yx]
656
+ end
657
+ res.reverse!
658
+ end
659
+
660
+ def self.first_path_cache_get_path_to_self(pix, path_cache)
661
+ frm = path_cache[pix.yx]
662
+ res = [pix]
663
+ while frm[0].yx != @pix.yx
664
+ res << frm[0]
665
+ frm = path_cache[frm[0].yx]
666
+ end
667
+ res << frm[0]
668
+ res.reverse!
669
+ end
670
+
671
+ def self.first_path_cache_get_ayx_path(pix, path_cache)
672
+ #$PDbgLog.sig_call(self)
673
+ #$PDbgLog.print_msg "pix#{pix.coords_to_s} path_cache: #{self.
674
+ # path_cache_to_s(path_cache)}: "
675
+ frm = path_cache[pix.a_yx]
676
+ res = [pix]
677
+ while frm[0]
678
+ #$PDbgLog.print_msg "#{frm[0].a_yx.inspect} "
679
+ res << frm[0]
680
+ frm = path_cache[frm[0].a_yx]
681
+ end
682
+ #$PDbgLog.sig_return
683
+ res.reverse!
684
+ end
685
+
686
+ def find_first_path_to(dest, max_lev=1.0/0.0, path_cache=nil,
687
+ &get_neighbs_levs)
688
+ if dest.kind_of?(Proc)
689
+ dest_proc = dest
690
+ else
691
+ dest_proc = proc {|px,lev| dest.a_eql?(px)}
692
+ end
693
+ tail = PMinHeap.new { |frm1,frm2| frm1[1] <=> frm2[1] }
694
+ unless path_cache
695
+ path_cache = @first_path_cache
696
+ unless dest.kind_of?(Proc)
697
+ return ImageObjectPixCalc.
698
+ first_path_cache_get_ayx_path(dest, path_cache) if
699
+ path_cache.include?(dest.a_yx)
700
+ end
701
+ path_cache.each_pair { |pix, frm|
702
+ tail.push([@get_pix_proc.call(pix[1], pix[0]),
703
+ frm[1]])
704
+ }
705
+ end
706
+ #$PDbgLog.sig_call(self)
707
+ path_cache[@pix.a_yx] = [nil, 0]
708
+ tail.push([@pix, 0])
709
+ if max_lev < 1
710
+ #$PDbgLog.sig_return("max_lev < 1: nil")
711
+ return nil
712
+ end
713
+ while !tail.empty?
714
+ #$PDbgLog.puts_msg "tail: " + tail.collect { |frm|
715
+ # (frm[0] ? frm[0].coords_to_s : frm[0].inspect) +
716
+ # ":#{frm[1]}" }.join(" ")
717
+ pix, lev = *tail.pop
718
+ #$PDbgLog.puts_msg "path_cache: #{ImageObjectPixCalc.
719
+ # path_cache_to_s(path_cache)}"
720
+ #$PDbgLog.print_msg pix.coords_to_s + ",#{lev}"
721
+ #$PDbgLog.print_msg "<-#{path_cache[pix.a_yx][0] ?
722
+ # path_cache[pix.a_yx][0].coords_to_s :
723
+ # path_cache[pix.a_yx][0].inspect} "
724
+ next if path_cache.include?(pix.a_yx) &&
725
+ path_cache[pix.a_yx][1] < lev
726
+ if dest_proc.call(pix, lev)
727
+ res = ImageObjectPixCalc.
728
+ first_path_cache_get_ayx_path(pix, path_cache)
729
+ #$PDbgLog.sig_return(PixbufPix.path_to_s(res))
730
+ return res
731
+ end
732
+ yield(pix, lev).each { |args| neighb, neighb_lev = *args
733
+ unless (path_cache.include?(neighb.a_yx) &&
734
+ path_cache[neighb.a_yx][1] <= neighb_lev) ||
735
+ neighb_lev > max_lev
736
+ tail.push([neighb, neighb_lev])
737
+ path_cache[neighb.a_yx]=[pix,neighb_lev]
738
+ end
739
+ }
740
+ end
741
+ #$PDbgLog.sig_return("nil")
742
+ nil
743
+ end
744
+
745
+ def kill_path_cache!
746
+ @path_cache.clear
747
+ @first_path_cache.clear
748
+ end
749
+ end
750
+
751
+ end