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