extract_curves 0.0.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 (99) 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/extconf.rb +22 -0
  18. data/ruby_ext/pav/pav.so +0 -0
  19. data/ruby_libs/CVS/Entries +1 -0
  20. data/ruby_libs/CVS/Repository +1 -0
  21. data/ruby_libs/CVS/Root +1 -0
  22. data/ruby_libs/pav/CVS/Entries +20 -0
  23. data/ruby_libs/pav/CVS/Repository +1 -0
  24. data/ruby_libs/pav/CVS/Root +1 -0
  25. data/ruby_libs/pav/attr_cache.rb +211 -0
  26. data/ruby_libs/pav/attr_cache.t1.rb +32 -0
  27. data/ruby_libs/pav/cache.rb +31 -0
  28. data/ruby_libs/pav/dbg_log.rb +458 -0
  29. data/ruby_libs/pav/floatsio.rb +53 -0
  30. data/ruby_libs/pav/generator_cache.rb +165 -0
  31. data/ruby_libs/pav/gtk/CVS/Entries +4 -0
  32. data/ruby_libs/pav/gtk/CVS/Repository +1 -0
  33. data/ruby_libs/pav/gtk/CVS/Root +1 -0
  34. data/ruby_libs/pav/gtk/button.rb +130 -0
  35. data/ruby_libs/pav/gtk/icons.rb +87 -0
  36. data/ruby_libs/pav/gtk/toolbar.rb +192 -0
  37. data/ruby_libs/pav/heap.rb +54 -0
  38. data/ruby_libs/pav/icons/CVS/Entries +17 -0
  39. data/ruby_libs/pav/icons/CVS/Repository +1 -0
  40. data/ruby_libs/pav/icons/CVS/Root +1 -0
  41. data/ruby_libs/pav/icons/alt_handle.xpm +3832 -0
  42. data/ruby_libs/pav/icons/alt_handle_hover.xpm +3368 -0
  43. data/ruby_libs/pav/icons/alt_handle_pressed.xpm +3828 -0
  44. data/ruby_libs/pav/icons/extract_curves/CVS/Entries +6 -0
  45. data/ruby_libs/pav/icons/extract_curves/CVS/Repository +1 -0
  46. data/ruby_libs/pav/icons/extract_curves/CVS/Root +1 -0
  47. data/ruby_libs/pav/icons/extract_curves/extract_curves-icon-rgb.ppm +14 -0
  48. data/ruby_libs/pav/icons/extract_curves/extract_curves-logo-rgb.gif +0 -0
  49. data/ruby_libs/pav/icons/extract_curves/trace_mark.xpm +38 -0
  50. data/ruby_libs/pav/icons/handle.xpm +213 -0
  51. data/ruby_libs/pav/icons/next.xpm +29 -0
  52. data/ruby_libs/pav/icons/next_hover.xpm +315 -0
  53. data/ruby_libs/pav/icons/next_pressed.xpm +144 -0
  54. data/ruby_libs/pav/icons/prev.xpm +29 -0
  55. data/ruby_libs/pav/icons/prev_hover.xpm +315 -0
  56. data/ruby_libs/pav/icons/prev_pressed.xpm +144 -0
  57. data/ruby_libs/pav/icons/vnext.xpm +29 -0
  58. data/ruby_libs/pav/icons/vprev.xpm +29 -0
  59. data/ruby_libs/pav/numeric/CVS/Entries +2 -0
  60. data/ruby_libs/pav/numeric/CVS/Repository +1 -0
  61. data/ruby_libs/pav/numeric/CVS/Root +1 -0
  62. data/ruby_libs/pav/numeric/ext.rb +13 -0
  63. data/ruby_libs/pav/pav_find.rb +90 -0
  64. data/ruby_libs/pav/pix/CVS/Entries +11 -0
  65. data/ruby_libs/pav/pix/CVS/Repository +1 -0
  66. data/ruby_libs/pav/pix/CVS/Root +1 -0
  67. data/ruby_libs/pav/pix/aapix.rb +378 -0
  68. data/ruby_libs/pav/pix/blob.rb +543 -0
  69. data/ruby_libs/pav/pix/circle.rb +73 -0
  70. data/ruby_libs/pav/pix/contour/CVS/Entries +5 -0
  71. data/ruby_libs/pav/pix/contour/CVS/Repository +1 -0
  72. data/ruby_libs/pav/pix/contour/CVS/Root +1 -0
  73. data/ruby_libs/pav/pix/contour/calc_situations.rb +9 -0
  74. data/ruby_libs/pav/pix/contour/carp_calc.rb +212 -0
  75. data/ruby_libs/pav/pix/contour/situations.dmp +0 -0
  76. data/ruby_libs/pav/pix/contour/situations.rb +21 -0
  77. data/ruby_libs/pav/pix/contour.rb +644 -0
  78. data/ruby_libs/pav/pix/curve.rb +1508 -0
  79. data/ruby_libs/pav/pix/img_obj.rb +751 -0
  80. data/ruby_libs/pav/pix/node.rb +712 -0
  81. data/ruby_libs/pav/pix/node_grp.rb +853 -0
  82. data/ruby_libs/pav/pix/shaved_core.rb +534 -0
  83. data/ruby_libs/pav/pix/subpix.rb +212 -0
  84. data/ruby_libs/pav/pix.rb +402 -0
  85. data/ruby_libs/pav/rand_accessible.rb +16 -0
  86. data/ruby_libs/pav/rangeset.rb +63 -0
  87. data/ruby_libs/pav/search.rb +210 -0
  88. data/ruby_libs/pav/set.rb +20 -0
  89. data/ruby_libs/pav/string/CVS/Entries +6 -0
  90. data/ruby_libs/pav/string/CVS/Repository +1 -0
  91. data/ruby_libs/pav/string/CVS/Root +1 -0
  92. data/ruby_libs/pav/string/bits.rb +523 -0
  93. data/ruby_libs/pav/string/ext.rb +58 -0
  94. data/ruby_libs/pav/string/observable.rb +155 -0
  95. data/ruby_libs/pav/string/text.rb +79 -0
  96. data/ruby_libs/pav/string/words.rb +42 -0
  97. data/ruby_libs/pav/sub_arr.rb +55 -0
  98. data/ruby_libs/pav/traced_obj.rb +79 -0
  99. metadata +147 -0
@@ -0,0 +1,644 @@
1
+ require 'set'
2
+ require 'pav/pix'
3
+ require 'pav/cache'
4
+ require 'pav/dbg_log'
5
+ require 'pav/pix/blob'
6
+ require 'pav/attr_cache'
7
+ require 'pav/pix/subpix'
8
+ require 'pav/pix/img_obj'
9
+ require 'pav/pix/contour/situations'
10
+
11
+ module PPix
12
+
13
+ class ContourLoop < ImageObject
14
+ attr_accessor :external, :contour_carpet, :vparities, :blob
15
+
16
+ self.img_obj_add_sub_obj :internal_blob
17
+
18
+ def initialize(contour_carpet=nil, external=nil)
19
+ @contour_carpet = contour_carpet
20
+ if external.nil?
21
+ @external = @contour_carpet.external if @contour_carpet
22
+ else
23
+ @external = external
24
+ end
25
+ @vparities = {}
26
+ super()
27
+ end
28
+
29
+ def merge_debris!(debris)
30
+ #$PDbgLog.sig_call(self)
31
+ debris.each { |pix|
32
+ ngbs = @contour_carpet.pix_neighbs(pix)
33
+ ngbs.each { |ngb|
34
+ if self.img_obj_yx_set.include?(ngb.yx)
35
+ j = self.index(ngb)
36
+ if ngbs.include?(self[i=j-1]) ||
37
+ ngbs.include?(self[((i=j)+1) % self.length])
38
+ #$PDbgLog.print_msg pix.coords_to_s+" @ #{i+1} "
39
+ #$PDbgLog.puts_msg PixbufPix.path_to_s(self)
40
+ self[i+1,0] = [pix]
41
+ self.img_obj_yx_set << pix.yx
42
+ #$PDbgLog.puts_msg PixbufPix.path_to_s(self)
43
+ break
44
+ end
45
+ end
46
+ }
47
+ }
48
+ #$PDbgLog.sig_return
49
+ end
50
+
51
+ def add(subpix)
52
+ if subpix.vertical?
53
+ if @vparities.include?(subpix.img_pix.yx)
54
+ @vparities.delete(subpix.img_pix.yx)
55
+ else
56
+ @vparities[subpix.img_pix.yx] = true
57
+ end
58
+ end
59
+ self << subpix.img_pix unless self[-1].yx==subpix.img_pix.yx
60
+ end
61
+
62
+ def add_pix(pix, horiz_cnt, vert_cnt)
63
+ if vert_cnt & 1 == 1
64
+ if @vparities.include?(pix.yx)
65
+ @vparities.delete(pix.yx)
66
+ else
67
+ @vparities[pix.yx] = true
68
+ end
69
+ end
70
+ self << pix
71
+ end
72
+
73
+ def internal_blob_each
74
+ return if self.empty?
75
+ #$PDbgLog.sig_call(self)
76
+ pix_scan = self.sort; pix_scan.uniq!
77
+ pixbuf = self.first.pixbuf
78
+ yield(pix_scan[0])
79
+ x0 = x = pix_scan[0].x
80
+ prev_y = y = pix_scan[0].y
81
+ parity = @vparities.include?(pix_scan[0].yx)
82
+ #$PDbgLog.puts_msg "pix_scan: #{PixbufPix.path_to_s(pix_scan)}"
83
+ #$PDbgLog.puts_msg "@vparities: " + PixbufPix.yx_path_to_s(
84
+ # @vparities.keys.to_a.sort)
85
+ if (i = 1) >= pix_scan.length
86
+ #$PDbgLog.sig_return
87
+ return
88
+ end
89
+ loop do
90
+ #$PDbgLog.print_msg "i=#{i}, x0=#{x0}, x=#{x}, y=#{y}: "
91
+ while pix_scan[i].y == y && pix_scan[i].x == x+1
92
+ #$PDbgLog.print_msg "."
93
+ x = pix_scan[i].x
94
+ parity ^= @vparities.include?(pix_scan[i].yx)
95
+ yield(pix_scan[i])
96
+ if (i += 1) >= pix_scan.length
97
+ #$PDbgLog.sig_return
98
+ return
99
+ end
100
+ end
101
+ #$PDbgLog.print_msg "; "
102
+ if pix_scan[i].y==y && parity
103
+ #$PDbgLog.print_msg "#{x}.upto(#{pix_scan[i].x
104
+ # }); "
105
+ (x+1).upto(pix_scan[i].x-1) { |tmp_x|
106
+ yield(pixbuf.get_pix(tmp_x, y)) }
107
+ end
108
+ x0 = x = pix_scan[i].x
109
+ y = pix_scan[i].y
110
+ parity ^= @vparities.include?(pix_scan[i].yx)
111
+ yield(pix_scan[i])
112
+ if (i += 1) >= pix_scan.length
113
+ #$PDbgLog.sig_return
114
+ return
115
+ end
116
+ end
117
+ #$PDbgLog.sig_return("Insanity!")
118
+ end
119
+
120
+ def internal_blob
121
+ $PDbgLog.sig_call(self)
122
+ res = ImageObject.new
123
+ self.internal_blob_each { |pix| res << pix }
124
+ $PDbgLog.sig_return
125
+ res.img_obj_freeze
126
+ res
127
+ end
128
+
129
+ def dup
130
+ res = self.class.new(contour_carpet, external)
131
+ res.replace(self)
132
+ res
133
+ end
134
+
135
+ cache_attr! :internal_blob
136
+ end
137
+
138
+ class ContourLoopCarpet < ContourLoop
139
+ self.img_obj_add_sub_obj()
140
+
141
+ def merge_new_loop!(lp)
142
+ if self.empty?
143
+ lp.each { |pix| self.img_obj_yx_set.add(pix.yx) }
144
+ self.replace(lp)
145
+ self.vparities.replace(lp.vparities)
146
+ return true
147
+ end
148
+ common_pix = common_pix_i = nil
149
+ lp.each_with_index { |pix, common_pix_i|
150
+ if self.img_obj_yx_set.include?(pix.yx)
151
+ common_pix = pix
152
+ break
153
+ end
154
+ }
155
+ if common_pix
156
+ lp.each { |pix| self.img_obj_yx_set.add(pix.yx) }
157
+ self[self.index(common_pix)+1,0] = lp[common_pix_i+
158
+ 1...lp.length] + lp[0..common_pix_i]
159
+ lp.vparities.each_key { |k|
160
+ if self.vparities.include?(k)
161
+ self.vparities.delete(k)
162
+ else self.vparities[k] = true; end }
163
+ return true
164
+ end
165
+ ngb = pix_i = nil
166
+ lp.each_with_index { |pix, pix_i|
167
+ self.contour_carpet.pix_neighbs(pix).each { |pngb|
168
+ if self.img_obj_yx_set.include?(pngb.yx)
169
+ ngb = pngb
170
+ break
171
+ end
172
+ }
173
+ break if ngb
174
+ }
175
+ return false unless ngb
176
+ lp.each { |pix| self.img_obj_yx_set.add(pix.yx) }
177
+ self[self.index(ngb)+1,0] = lp[pix_i...lp.length] +
178
+ lp[0..pix_i] + [ngb]
179
+ lp.vparities.each_key { |k|
180
+ if self.vparities.include?(k)
181
+ self.vparities.delete(k)
182
+ else self.vparities[k] = true; end }
183
+ end
184
+ end
185
+
186
+ class PixbufPix
187
+ attr_accessor :border_dirs8_id, :subpix_path_dir
188
+ end
189
+
190
+ class ContourCarpetCalc
191
+ attr_reader :contour_carpet, :geometry, :external, :block, :cpix,
192
+ :start_pix
193
+
194
+ def initialize(contour_carpet, geometry=8, external=nil, &block)
195
+ @contour_carpet = contour_carpet
196
+ @geometry = geometry
197
+ if external.nil?
198
+ @external = contour_carpet.external
199
+ else @external = external; end
200
+ if block_given?
201
+ @block = block
202
+ else
203
+ @block = nil
204
+ end
205
+ @start_pix = @contour_carpet.start_pix
206
+ @visited = {}
207
+ @pix_calcs = {}
208
+ end
209
+
210
+ def each_cpix(&block)
211
+ block = @block unless block_given?
212
+ block.call(@contour_carpet.start_pix)
213
+ @visited = { @contour_carpet.start_pix.yx => true }
214
+ @cpix = @contour_carpet.start_pix
215
+ tail = [@cpix]
216
+ while !tail.empty?
217
+ @contour_carpet.pix_neighbs(tail.pop).each { |cpix|
218
+ next if @visited.include?(cpix.yx)
219
+ block.call(cpix)
220
+ @visited[cpix.yx] = true
221
+ tail.push(cpix)
222
+ }
223
+ end
224
+ end
225
+
226
+ def loop_indexes(pix)
227
+ res = []
228
+ @loop.each_with_index { |p, i|
229
+ res << i if p.y == pix.y && p.x == pix.x }
230
+ res
231
+ end
232
+
233
+ def get_calc
234
+ @pix_calcs[@cpix.yx] = ImageObjectPixCalc.new(@cpix) unless
235
+ @pix_calcs.include?(@cpix.yx)
236
+ @pix_calcs[@cpix.yx]
237
+ end
238
+
239
+ def next_loop(start_subpix, id2lm, external)
240
+ #$PDbgLog.sig_call(self)
241
+ i_res = []
242
+ pix = start_subpix.img_pix
243
+ lm = id2lm.at(ContourCarpetCalc.subpix_situ8_pack(
244
+ @contour_carpet.pix_situ8_arr_into(pix, i_res))).at(
245
+ start_subpix.sub_n)
246
+ pix.border_dirs8_id = lm.border_dirs8_id
247
+ lp = ContourLoop.new(@contour_carpet, external)
248
+ lp.add_pix(pix, lm.path_horiz_cnt, lm.path_vert_cnt)
249
+ #$PDbgLog.puts_msg "start_subpix#{start_subpix}, external=#{
250
+ # external}, lm=#{lm.inspect}"
251
+ if external
252
+ next_lm = lm.entry
253
+ pix.subpix_path_dir = -1
254
+ else
255
+ next_lm = lm.exit
256
+ pix.subpix_path_dir = +1
257
+ end
258
+ if @visited.include?([pix.y, pix.x, lm.border_dirs8_id]) ||
259
+ !next_lm
260
+ #$PDbgLog.sig_return('debris.')
261
+ return lp
262
+ end
263
+ @visited[[pix.y,pix.x,lm.border_dirs8_id]] = true
264
+ pixbuf = pix.pixbuf
265
+ pix = pixbuf.get_pix(pix.x + next_lm.x, pix.y + next_lm.y)
266
+ lm = id2lm.at(ContourCarpetCalc.subpix_situ8_pack(
267
+ @contour_carpet.pix_situ8_arr_into(pix, i_res))).
268
+ at(next_lm.sub_n)
269
+ pix.border_dirs8_id = lm.border_dirs8_id
270
+ #$PDbgLog.new_progr
271
+ #$PDbgLog.progr.show_as = "/ visited"
272
+ while !@visited.include?([pix.y, pix.x, lm.border_dirs8_id])
273
+ #$PDbgLog.puts_msg "#{pix.coords_to_s}" +
274
+ # ",lm=#{lm} "
275
+ # ",dirs_id=#{"%b" % lm.border_dirs8_id}"
276
+ lp.add_pix(pix, lm.path_horiz_cnt, lm.path_vert_cnt)
277
+ @visited[[pix.y,pix.x,lm.border_dirs8_id]] = true
278
+ p_entry = pixbuf.get_pix(pix.x + lm.entry.x,
279
+ pix.y + lm.entry.y)
280
+ lm_entry = id2lm.at(ContourCarpetCalc.subpix_situ8_pack(
281
+ @contour_carpet.pix_situ8_arr_into(p_entry, i_res))).
282
+ at(lm.entry.sub_n)
283
+ p_exit = pixbuf.get_pix(pix.x + lm.exit.x,
284
+ pix.y + lm.exit.y)
285
+ lm_exit = id2lm.at(ContourCarpetCalc.subpix_situ8_pack(
286
+ @contour_carpet.pix_situ8_arr_into(p_exit, i_res))).
287
+ at(lm.exit.sub_n)
288
+ if @visited.include?([p_entry.y, p_entry.x,
289
+ lm_entry.border_dirs8_id])
290
+ pix.subpix_path_dir = +1
291
+ #$PDbgLog.print_msg ",next sub_n=#{lm.exit.sub_n
292
+ # }"
293
+ pix = p_exit; lm = lm_exit
294
+ else
295
+ # $PDbgLog.print_msg ",next sub_n=#{lm.entry.sub_n
296
+ # }"
297
+ pix.subpix_path_dir = -1
298
+ pix = p_entry; lm = lm_entry
299
+ end
300
+ #$PDbgLog.print_msg ",subpix_path_dir=" +
301
+ # lp.last.subpix_path_dir.inspect + " "
302
+ pix.border_dirs8_id = lm.border_dirs8_id
303
+ #$PDbgLog.progr.progr_units = @visited.length
304
+ end
305
+ #$PDbgLog.sig_return(".")
306
+ lp
307
+ end
308
+
309
+ def get_loops
310
+ return [ContourLoop.new(@contour_carpet).
311
+ replace(@contour_carpet)] if @contour_carpet.length < 3
312
+ #$PDbgLog.sig_call(self)
313
+ loops = []
314
+ @visited.clear
315
+ unvis_neighbs = []
316
+ vis_pix = {}
317
+ debris = Set.new
318
+ start_cpix = @contour_carpet.first
319
+ if @external
320
+ if @geometry == 8
321
+ get_start_subpix_proc = proc{|cpix| cpix.subpix8(16)}
322
+ id2lm = ContourCarpetCalc::CONTOUR_PATH_EXTERNAL_SITU8_ID2LM
323
+ else
324
+ get_start_subpix_proc = proc{|cpix| cpix.subpix4(8)}
325
+ id2lm = ContourCarpetCalc::CONTOUR_PATH_EXTERNAL_SITU4_ID2LM
326
+ end
327
+ else
328
+ if @geometry == 8
329
+ get_start_subpix_proc = proc{|cpix| cpix.subpix8(16)}
330
+ id2lm = ContourCarpetCalc::CONTOUR_PATH_INTERNAL_SITU8_ID2LM
331
+ else
332
+ get_start_subpix_proc = proc{|cpix| cpix.subpix4(8)}
333
+ id2lm = ContourCarpetCalc::CONTOUR_PATH_INTERNAL_SITU4_ID2LM
334
+ end
335
+ end
336
+ #$PDbgLog.print_msg "@external=#{@external.inspect} "
337
+ while start_cpix
338
+ #$PDbgLog.print_msg "start_cpix: #{start_cpix}: "
339
+ lp = self.next_loop(get_start_subpix_proc.call(
340
+ start_cpix), id2lm, @external)
341
+ #$PDbgLog.print_msg PixbufPix.path_to_s(lp) + " "
342
+ #$PDbgLog.puts_msg lp.inspect
343
+ #$PDbgLog.puts_msg "#{lp.length} pix "
344
+ if lp.length > 1
345
+ loops << lp
346
+ else
347
+ debris << start_cpix
348
+ end
349
+ lp.each { |pix| vis_pix[pix.yx] = true }
350
+ lp.each{|pix|@contour_carpet.pix_neighbs(pix).each{|ngb|
351
+ unvis_neighbs << ngb unless vis_pix.include?(ngb.yx)||
352
+ debris.include?(ngb) }}
353
+ start_cpix = unvis_neighbs.pop
354
+ while start_cpix && (vis_pix.include?(start_cpix.yx) ||
355
+ debris.include?(start_cpix))
356
+ start_cpix = unvis_neighbs.pop
357
+ end
358
+ end
359
+ loops.each { |lp| lp.merge_debris!(debris) }
360
+ #$PDbgLog.sig_return(".")
361
+ loops
362
+ end
363
+ end
364
+
365
+ class ContourCarpet < ImageObject
366
+ attr_reader :start_pix, :pix_neighbs_proc, :geometry, :external, :blob,
367
+ :min_loop_length, :subpix_class, :pix_neighbs_cache
368
+
369
+ self.img_obj_add_sub_obj :loops, :loop_carpet
370
+
371
+ def initialize(pix, blob, geometry=8, external=true, min_loop_length=0)
372
+ raise ArgumentError, "geometry must be 8 or 4" unless
373
+ [8, 4].include?(@geometry = geometry)
374
+ @external = external
375
+ @blob = blob
376
+ @min_loop_length = min_loop_length
377
+ @subpix_class = [Subpix4,Subpix8].at(@geometry/4 - 1)
378
+ @loops = nil
379
+ @loop_carpet = nil
380
+ if block_given?
381
+ @pix_neighbs_proc = Proc.new
382
+ else
383
+ if geometry == 8
384
+ @pix_neighbs_proc = proc{|ppix| ppix.adj8.find_all{|pix|
385
+ @blob.pixbuf.blob_id_at?(pix.x,pix.y,@blob.blob_id)&&
386
+ ((adj4 = pix.adj4).length < 4 ||
387
+ adj4.detect { |p|
388
+ !@blob.pixbuf.blob_id_at?(p.x,p.y,@blob.blob_id)})
389
+ }}
390
+ else
391
+ @pix_neighbs_proc = proc{|ppix| ppix.adj4.find_all{|pix|
392
+ @blob.pixbuf.blob_id_at?(pix.x,pix.y,@blob.blob_id)&&
393
+ ((adj8 = pix.adj8).length < 8 ||
394
+ adj8.detect { |p|
395
+ !@blob.pixbuf.blob_id_at?(p.x,p.y,@blob.blob_id)})
396
+ }}
397
+ end
398
+ end
399
+ super()
400
+ @start_pix = pix
401
+ @pix_rev_conn_idxs = {}
402
+ @pix_neighbs_cache = PCache.new
403
+ self.rebuild
404
+ end
405
+
406
+ def rebuild
407
+ $PDbgLog.sig_call(self)
408
+ self.clear
409
+ @loops = @loop_carpet = nil
410
+ $PDbgLog.print_msg "Getting #{@external ? "external": "internal"
411
+ } contour carpet from #{@start_pix.coords_to_s}: "
412
+ ContourCarpetCalc.new(self, @geometry, @external).each_cpix {
413
+ |cpix| self << cpix }
414
+ @pix_neighbs_cache.clear
415
+ $PDbgLog.sig_return("#{self.length} pixel#{self.length==1 ? "" :
416
+ "s"}.\n")
417
+ end
418
+
419
+ def loops
420
+ return @loops if @loops
421
+ @loops = ContourCarpetCalc.new(self, @geometry, @external).
422
+ get_loops.delete_if{ |lp| lp.length < @min_loop_length }
423
+ @loops.each { |lp| lp.blob = @blob }
424
+ @pix_neighbs_cache.clear
425
+ @loops
426
+ end
427
+
428
+ def loop_carpet
429
+ return @loop_carpet if @loop_carpet
430
+ $PDbgLog.sig_call(self)
431
+ $PDbgLog.print_msg "Getting #{@external ? "external": "internal"
432
+ } loop carpet: "
433
+ @loop_carpet = ContourLoopCarpet.new(self)
434
+ self.loops.each { |lp| @loop_carpet.merge_new_loop!(lp) }
435
+ @loop_carpet.blob = @blob
436
+ #$PDbgLog.print_msg PixbufPix.path_to_s(@loop_carpet) + ": "
437
+ @loop_carpet.img_obj_freeze
438
+ $PDbgLog.sig_return("#{@loop_carpet.length} pixel#{@loop_carpet.
439
+ length == 1 ? "" : "s"}.\n")
440
+ @loop_carpet
441
+ end
442
+
443
+ def to_s
444
+ "<PPix::ContourCarpet start_pix#{@start_pix.coords_to_s
445
+ }, geometry=#{@geometry} in pixbuf: #{@start_pix.pixbuf
446
+ }>"
447
+ end
448
+
449
+ alias_method :inspect, :to_s
450
+ end
451
+
452
+ class ContourCarpet
453
+ def pix_neighbs(pix)
454
+ if (tmp = @pix_neighbs_cache[pix.yx])
455
+ return tmp
456
+ end
457
+ @pix_neighbs_cache[pix.yx] = self.pix_neighbs_proc.call(pix)
458
+ end
459
+
460
+ def pix_connections(pix)
461
+ pix.connections { |cpix| self.pix_neighbs(cpix) }
462
+ end
463
+
464
+ def pix_rev_conn_idx(pix, conn_i)
465
+ #$PDbgLog.sig_call(self)
466
+ #$PDbgLog.puts_msg "(#{conn_i}) from (#{self.x}, #{self.y})."
467
+ if (rci = @pix_rev_conn_idxs[pix.yx])
468
+ return rci[conn_i] if rci[conn_i]
469
+ else
470
+ rci = @pix_rev_conn_idxs[pix.yx] = []
471
+ end
472
+ conns = self.pix_connections(pix)
473
+ #$PDbgLog.sig_return
474
+ rci[conn_i] = pix.rev_conn_idx(conns, conn_i,
475
+ self.pix_connections(conns[conn_i].last))
476
+ end
477
+
478
+ def pix_node?(pix)
479
+ self.pix_neighbs(pix).length > 2
480
+ end
481
+
482
+ def pix_transit_point?(pix)
483
+ self.pix_neighbs(pix).length == 2
484
+ end
485
+
486
+ def pix_end_point?(pix)
487
+ self.pix_neighbs(pix).length < 2
488
+ end
489
+
490
+ def pix_has_node_neighb?(pix)
491
+ self.pix_neighbs(pix).each { |neighb|
492
+ return true if self.pix_node?(neighb) }
493
+ false
494
+ end
495
+
496
+ def pix_has_nonnode_neighb?(pix)
497
+ self.pix_neighbs(pix).each { |neighb|
498
+ return true if !self.pix_node?(neighb) }
499
+ false
500
+ end
501
+
502
+ def pix_in_node_grp?(pix)
503
+ self.pix_node?(pix) && !self.pix_has_nonnode_neighb?(pix)
504
+ end
505
+ end
506
+
507
+ class ContourCarpet
508
+ def subpix_internal_neighbs(subpix)
509
+ #$PDbgLog.sig_call(self)
510
+ incl_yx=self.pix_neighbs(subpix.img_pix).collect{|cpix| cpix.yx}
511
+ incl_yx << subpix.img_pix.yx
512
+ yx_set = self.img_obj_yx_set
513
+ pixbuf = self.blob.pixbuf
514
+ blob_id = self.blob.blob_id
515
+ #$PDbgLog.puts_msg "yx_set: " + PixbufPix.yx_path_to_s(
516
+ # yx_set.to_a.sort)
517
+ #res =
518
+ subpix.neighbs.find_all { |ngb|
519
+ #$PDbgLog.print_msg ngb.to_s + " "
520
+ incl_yx.include?(ngb.img_pix.yx) &&
521
+ ngb.border.detect { |nn|
522
+ !yx_set.include?(nn.img_pix.yx) && (
523
+ nn.img_pix.virtual? ||
524
+ !pixbuf.blob_id_at?(nn.img_pix.x, nn.img_pix.y,
525
+ blob_id) )
526
+ }
527
+ }
528
+ #$PDbgLog.print_msg ". "
529
+ #$PDbgLog.sig_return(subpix.to_s + ": " + Subpix.path_to_s(res))
530
+ #res
531
+ end
532
+
533
+ def subpix_external_neighbs(subpix)
534
+ #$PDbgLog.sig_call(self)
535
+ incl_yx =self.pix_neighbs(subpix.img_pix).collect{|cpix|cpix.yx}
536
+ incl_yx << subpix.img_pix.yx
537
+ yx_set = self.img_obj_yx_set
538
+ pixbuf = self.blob.pixbuf
539
+ blob_id = self.blob.blob_id
540
+ #$PDbgLog.puts_msg "yx_set: " + PixbufPix.yx_path_to_s(
541
+ # yx_set.to_a.sort)
542
+ #res =
543
+ subpix.neighbs.find_all { |ngb|
544
+ #$PDbgLog.print_msg ngb.to_s + " "
545
+ incl_yx.include?(ngb.img_pix.yx) &&
546
+ ngb.border.detect { |nn|
547
+ !yx_set.include?(nn.img_pix.yx) && (
548
+ !nn.img_pix.virtual? &&
549
+ pixbuf.blob_id_at?(nn.img_pix.x, nn.img_pix.y,
550
+ blob_id) )
551
+ }
552
+ }
553
+ #$PDbgLog.print_msg ". "
554
+ #$PDbgLog.sig_return(subpix.to_s + ": " + Subpix.path_to_s(res))
555
+ #res
556
+ end
557
+
558
+ def subpix_internal_neighbs_into(subpix, res=[], incl_yx=[], neighbs=[],
559
+ bordr=[])
560
+ #$PDbgLog.sig_call(self)
561
+ incl_yx.clear
562
+ self.pix_neighbs(subpix.img_pix).each{|cpix| incl_yx << cpix.yx}
563
+ incl_yx << subpix.img_pix.yx
564
+ yx_set = self.img_obj_yx_set
565
+ pixbuf = self.blob.pixbuf
566
+ blob_id = self.blob.blob_id
567
+ #$PDbgLog.puts_msg "yx_set: " + PixbufPix.yx_path_to_s(
568
+ # yx_set.to_a.sort)
569
+ res.clear
570
+ subpix.neighbs_into(neighbs).each { |ngb|
571
+ #$PDbgLog.print_msg ngb.to_s + " "
572
+ if incl_yx.include?(ngb.img_pix.yx) &&
573
+ ngb.border_into(bordr).detect { |nn|
574
+ !yx_set.include?(nn.img_pix.yx) && (
575
+ nn.img_pix.virtual? ||
576
+ !pixbuf.blob_id_at?(nn.img_pix.x, nn.img_pix.y,
577
+ blob_id) )
578
+ }
579
+ res << ngb
580
+ end
581
+ }
582
+ #$PDbgLog.print_msg ". "
583
+ #$PDbgLog.sig_return(subpix.to_s + ": " + Subpix.path_to_s(res))
584
+ res
585
+ end
586
+
587
+ def subpix_external_neighbs_into(subpix, res=[], incl_yx=[], neighbs=[],
588
+ bordr=[])
589
+ #$PDbgLog.sig_call(self)
590
+ incl_yx.clear
591
+ self.pix_neighbs(subpix.img_pix).each{|cpix|incl_yx << cpix.yx}
592
+ incl_yx << subpix.img_pix.yx
593
+ yx_set = self.img_obj_yx_set
594
+ pixbuf = self.blob.pixbuf
595
+ blob_id = self.blob.blob_id
596
+ #$PDbgLog.puts_msg "yx_set: " + PixbufPix.yx_path_to_s(
597
+ # yx_set.to_a.sort)
598
+ res.clear
599
+ subpix.neighbs_into(neighbs).each { |ngb|
600
+ #$PDbgLog.print_msg ngb.to_s + " "
601
+ if incl_yx.include?(ngb.img_pix.yx) &&
602
+ ngb.border_into(bordr).detect { |nn|
603
+ !yx_set.include?(nn.img_pix.yx) && (
604
+ !nn.img_pix.virtual? &&
605
+ pixbuf.blob_id_at?(nn.img_pix.x, nn.img_pix.y,
606
+ blob_id) )
607
+ }
608
+ res << ngb
609
+ end
610
+ }
611
+ #$PDbgLog.print_msg ". "
612
+ #$PDbgLog.sig_return(subpix.to_s + ": " + Subpix.path_to_s(res))
613
+ res
614
+ end
615
+
616
+ def subpix_neighbs(subpix, external=true)
617
+ external ? self.subpix_external_neighbs(subpix) :
618
+ self.subpix_internal_neighbs(subpix)
619
+ end
620
+ end
621
+
622
+ class ContourCarpet
623
+ def pix_situ8_arr_into(pix, res=[])
624
+ res.clear
625
+ self.pix_neighbs(pix).each { |px| res[PixbufPix::ADJ8_ID2SPEC.
626
+ at(PixbufPix.adj8_xy_id(px.x-pix.x, px.y-pix.y)).at(1)] = 1 }
627
+ pixbuf = pix.pixbuf
628
+ blob_id = self.blob.blob_id
629
+ width = pixbuf.picture_width; height = pixbuf.picture_height
630
+ PixbufPix::ADJ8_CCW_ORDER.each_with_index { |a,a_i|
631
+ next if res.at(a_i)
632
+ x = pix.x + a.x; y = pix.y + a.y
633
+ if y >= 0 && y < height && x >= 0 && x < width &&
634
+ pixbuf.blob_id_at?(x, y, blob_id)
635
+ res[a_i] = 2
636
+ else
637
+ res[a_i] = 0
638
+ end
639
+ }
640
+ res
641
+ end
642
+ end
643
+
644
+ end