extract-curves 0.1.1

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 (172) 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/cstr.c +82 -0
  11. data/ruby_ext/pav/cstr.h +17 -0
  12. data/ruby_ext/pav/extconf.rb +22 -0
  13. data/ruby_ext/pav/pav.c +162 -0
  14. data/ruby_ext/pav/pgtk.c +40 -0
  15. data/ruby_ext/pav/pgtk.h +14 -0
  16. data/ruby_ext/pav/pix.c +806 -0
  17. data/ruby_ext/pav/pix.h +236 -0
  18. data/ruby_ext/pav/t.rb +35 -0
  19. data/ruby_ext/pav/t1.rb +35 -0
  20. data/ruby_libs/pav/attr_cache.rb +211 -0
  21. data/ruby_libs/pav/attr_cache.t1.rb +32 -0
  22. data/ruby_libs/pav/cache.rb +31 -0
  23. data/ruby_libs/pav/collection/std.rb +58 -0
  24. data/ruby_libs/pav/dbg_log.rb +458 -0
  25. data/ruby_libs/pav/floatsio.rb +53 -0
  26. data/ruby_libs/pav/generator_cache.rb +165 -0
  27. data/ruby_libs/pav/graph/node.rb +602 -0
  28. data/ruby_libs/pav/graph/node_grp.rb +865 -0
  29. data/ruby_libs/pav/gtk.rb +6 -0
  30. data/ruby_libs/pav/gtk/button.rb +118 -0
  31. data/ruby_libs/pav/gtk/dialog.rb +29 -0
  32. data/ruby_libs/pav/gtk/guiobj.rb +772 -0
  33. data/ruby_libs/pav/gtk/icons.rb +124 -0
  34. data/ruby_libs/pav/gtk/rulers.rb +264 -0
  35. data/ruby_libs/pav/gtk/toolbar.rb +189 -0
  36. data/ruby_libs/pav/guiobj.rb +2 -0
  37. data/ruby_libs/pav/guiobj/info_asm.rb +41 -0
  38. data/ruby_libs/pav/guiobj/method.rb +211 -0
  39. data/ruby_libs/pav/guiobj/obj.rb +134 -0
  40. data/ruby_libs/pav/guiobj/signals.rb +9 -0
  41. data/ruby_libs/pav/heap.rb +54 -0
  42. data/ruby_libs/pav/icons/alt_handle.xcf +0 -0
  43. data/ruby_libs/pav/icons/alt_handle.xpm +3832 -0
  44. data/ruby_libs/pav/icons/alt_handle_hover.xcf +0 -0
  45. data/ruby_libs/pav/icons/alt_handle_hover.xpm +3368 -0
  46. data/ruby_libs/pav/icons/alt_handle_pressed.xcf +0 -0
  47. data/ruby_libs/pav/icons/alt_handle_pressed.xpm +3828 -0
  48. data/ruby_libs/pav/icons/blob.gif +0 -0
  49. data/ruby_libs/pav/icons/clover_base.xcf +0 -0
  50. data/ruby_libs/pav/icons/contour.gif +0 -0
  51. data/ruby_libs/pav/icons/contour.xcf +0 -0
  52. data/ruby_libs/pav/icons/contour_carpet.gif +0 -0
  53. data/ruby_libs/pav/icons/contour_carpet.xcf +0 -0
  54. data/ruby_libs/pav/icons/curve.gif +0 -0
  55. data/ruby_libs/pav/icons/curve.xcf +0 -0
  56. data/ruby_libs/pav/icons/curve_carpet.gif +0 -0
  57. data/ruby_libs/pav/icons/curve_carpet.xcf +0 -0
  58. data/ruby_libs/pav/icons/expand_base.xcf +0 -0
  59. data/ruby_libs/pav/icons/expand_closed.xpm +1791 -0
  60. data/ruby_libs/pav/icons/expand_closed_hover.xpm +1775 -0
  61. data/ruby_libs/pav/icons/expand_open.xpm +1788 -0
  62. data/ruby_libs/pav/icons/expand_open_hover.xpm +1752 -0
  63. data/ruby_libs/pav/icons/extract_curves/extract_curves-icon-rgb.ppm +14 -0
  64. data/ruby_libs/pav/icons/extract_curves/extract_curves-logo-rgb.gif +0 -0
  65. data/ruby_libs/pav/icons/extract_curves/extract_curves-logo-rgb.xcf +0 -0
  66. data/ruby_libs/pav/icons/extract_curves/trace_mark.xcf +0 -0
  67. data/ruby_libs/pav/icons/extract_curves/trace_mark.xpm +38 -0
  68. data/ruby_libs/pav/icons/handle.xcf +0 -0
  69. data/ruby_libs/pav/icons/handle.xpm +213 -0
  70. data/ruby_libs/pav/icons/loop.gif +0 -0
  71. data/ruby_libs/pav/icons/loop.xcf +0 -0
  72. data/ruby_libs/pav/icons/loop_carpet.gif +0 -0
  73. data/ruby_libs/pav/icons/loop_carpet.xcf +0 -0
  74. data/ruby_libs/pav/icons/next.xpm +29 -0
  75. data/ruby_libs/pav/icons/next_hover.xpm +315 -0
  76. data/ruby_libs/pav/icons/next_pressed.xpm +144 -0
  77. data/ruby_libs/pav/icons/prev.xpm +29 -0
  78. data/ruby_libs/pav/icons/prev_hover.xpm +315 -0
  79. data/ruby_libs/pav/icons/prev_pressed.xpm +144 -0
  80. data/ruby_libs/pav/icons/shaved-core.gif +0 -0
  81. data/ruby_libs/pav/icons/vnext.xpm +29 -0
  82. data/ruby_libs/pav/icons/vprev.xpm +29 -0
  83. data/ruby_libs/pav/numeric/ext.rb +21 -0
  84. data/ruby_libs/pav/patterns/hsep.gif +0 -0
  85. data/ruby_libs/pav/patterns/tnode.gif +0 -0
  86. data/ruby_libs/pav/patterns/tnode_w_link.gif +0 -0
  87. data/ruby_libs/pav/patterns/vlink.gif +0 -0
  88. data/ruby_libs/pav/patterns/vsep.gif +0 -0
  89. data/ruby_libs/pav/patterns/yg_hrope.xpm +492 -0
  90. data/ruby_libs/pav/patterns/yg_hrope_thick.xpm +1904 -0
  91. data/ruby_libs/pav/patterns/yg_hrope_thin.xpm +130 -0
  92. data/ruby_libs/pav/patterns/yg_tnode.xpm +180 -0
  93. data/ruby_libs/pav/patterns/yg_tnode_thick.xpm +615 -0
  94. data/ruby_libs/pav/patterns/yg_tnode_thin.xpm +55 -0
  95. data/ruby_libs/pav/patterns/yg_tnode_w_link.xpm +190 -0
  96. data/ruby_libs/pav/patterns/yg_tnode_w_link_thick.xpm +676 -0
  97. data/ruby_libs/pav/patterns/yg_tnode_w_link_thin.xpm +62 -0
  98. data/ruby_libs/pav/patterns/yg_vrope.xpm +563 -0
  99. data/ruby_libs/pav/patterns/yg_vrope_thick.xpm +2047 -0
  100. data/ruby_libs/pav/patterns/yg_vrope_thin.xpm +166 -0
  101. data/ruby_libs/pav/pav_find.rb +90 -0
  102. data/ruby_libs/pav/pix.rb +402 -0
  103. data/ruby_libs/pav/pix/aapix.rb +378 -0
  104. data/ruby_libs/pav/pix/blob.rb +678 -0
  105. data/ruby_libs/pav/pix/circle.rb +73 -0
  106. data/ruby_libs/pav/pix/contour.rb +676 -0
  107. data/ruby_libs/pav/pix/contour/calc_situations.rb +9 -0
  108. data/ruby_libs/pav/pix/contour/carp_calc.rb +212 -0
  109. data/ruby_libs/pav/pix/contour/situations.dmp +0 -0
  110. data/ruby_libs/pav/pix/contour/situations.rb +21 -0
  111. data/ruby_libs/pav/pix/curve.rb +1544 -0
  112. data/ruby_libs/pav/pix/img_obj.rb +865 -0
  113. data/ruby_libs/pav/pix/node.rb +159 -0
  114. data/ruby_libs/pav/pix/shaved_core.rb +697 -0
  115. data/ruby_libs/pav/pix/subpix.rb +212 -0
  116. data/ruby_libs/pav/rand_accessible.rb +16 -0
  117. data/ruby_libs/pav/rangeset.rb +63 -0
  118. data/ruby_libs/pav/search.rb +210 -0
  119. data/ruby_libs/pav/set.rb +130 -0
  120. data/ruby_libs/pav/string/bits.rb +523 -0
  121. data/ruby_libs/pav/string/ext.rb +58 -0
  122. data/ruby_libs/pav/string/observable.rb +155 -0
  123. data/ruby_libs/pav/string/text.rb +79 -0
  124. data/ruby_libs/pav/string/words.rb +42 -0
  125. data/ruby_libs/pav/sub_arr.rb +56 -0
  126. data/ruby_libs/pav/traced_obj.rb +79 -0
  127. data/web/index.html +280 -0
  128. data/web/media/icons/alt_handle.xcf +0 -0
  129. data/web/media/icons/alt_handle.xpm +3832 -0
  130. data/web/media/icons/alt_handle_hover.xcf +0 -0
  131. data/web/media/icons/alt_handle_hover.xpm +3368 -0
  132. data/web/media/icons/alt_handle_pressed.xcf +0 -0
  133. data/web/media/icons/alt_handle_pressed.xpm +3828 -0
  134. data/web/media/icons/blob.gif +0 -0
  135. data/web/media/icons/clover_base.xcf +0 -0
  136. data/web/media/icons/contour.gif +0 -0
  137. data/web/media/icons/contour.xcf +0 -0
  138. data/web/media/icons/contour_carpet.gif +0 -0
  139. data/web/media/icons/contour_carpet.xcf +0 -0
  140. data/web/media/icons/curve.gif +0 -0
  141. data/web/media/icons/curve.xcf +0 -0
  142. data/web/media/icons/curve_carpet.gif +0 -0
  143. data/web/media/icons/curve_carpet.xcf +0 -0
  144. data/web/media/icons/expand_base.xcf +0 -0
  145. data/web/media/icons/expand_closed.xpm +1791 -0
  146. data/web/media/icons/expand_closed_hover.xpm +1775 -0
  147. data/web/media/icons/expand_open.xpm +1788 -0
  148. data/web/media/icons/expand_open_hover.xpm +1752 -0
  149. data/web/media/icons/extract_curves/extract_curves-icon-rgb.ppm +14 -0
  150. data/web/media/icons/extract_curves/extract_curves-logo-rgb.gif +0 -0
  151. data/web/media/icons/extract_curves/extract_curves-logo-rgb.xcf +0 -0
  152. data/web/media/icons/extract_curves/trace_mark.xcf +0 -0
  153. data/web/media/icons/extract_curves/trace_mark.xpm +38 -0
  154. data/web/media/icons/handle.xcf +0 -0
  155. data/web/media/icons/handle.xpm +213 -0
  156. data/web/media/icons/loop.gif +0 -0
  157. data/web/media/icons/loop.xcf +0 -0
  158. data/web/media/icons/loop_carpet.gif +0 -0
  159. data/web/media/icons/loop_carpet.xcf +0 -0
  160. data/web/media/icons/next.xpm +29 -0
  161. data/web/media/icons/next_hover.xpm +315 -0
  162. data/web/media/icons/next_pressed.xpm +144 -0
  163. data/web/media/icons/prev.xpm +29 -0
  164. data/web/media/icons/prev_hover.xpm +315 -0
  165. data/web/media/icons/prev_pressed.xpm +144 -0
  166. data/web/media/icons/shaved-core.gif +0 -0
  167. data/web/media/icons/vnext.xpm +29 -0
  168. data/web/media/icons/vprev.xpm +29 -0
  169. data/web/media/title.jpeg +0 -0
  170. data/web/media/title.xcf +0 -0
  171. data/web/stylesheets/default.css +20 -0
  172. metadata +229 -0
@@ -0,0 +1,53 @@
1
+ class FloatsInp
2
+ @@float_pat = Regexp.compile(/[+-]?(?:[0-9]+[.]?[0-9]*|[0-9]*[.]?[0-9]+)(?:[eE]?[0-9]*[.]?[0-9]*|)/)
3
+
4
+ attr_reader :io, :rec_buf
5
+
6
+ def initialize(*args)
7
+ @rec_buf = []
8
+ if args[0].kind_of?(IO)
9
+ @io = args[0]
10
+ else
11
+ @io = File.new(*args)
12
+ end
13
+ end
14
+
15
+ def method_missing(id, *args, &block)
16
+ @io.send(id, *args, &block)
17
+ end
18
+
19
+ def get_float
20
+ if @rec_buf.empty? && (ln = self.gets)
21
+ ln.scan(@@float_pat) { |f| @rec_buf << f.to_f }
22
+ end
23
+ @rec_buf.shift
24
+ end
25
+
26
+ def each_float
27
+ while (f = self.get_float)
28
+ yield(f)
29
+ end
30
+ end
31
+
32
+ def get_rec
33
+ if @rec_buf.empty?
34
+ return nil unless (ln = self.gets)
35
+ ln.scan(@@float_pat) { |f| @rec_buf << f.to_f }
36
+ end
37
+ res = @rec_buf
38
+ @rec_buf = []
39
+ res
40
+ end
41
+
42
+ def each_rec
43
+ while (rec = self.get_rec)
44
+ yield(rec)
45
+ end
46
+ end
47
+
48
+ def read_recs
49
+ res = []
50
+ self.each_rec { |rec| res << rec }
51
+ res
52
+ end
53
+ end
@@ -0,0 +1,165 @@
1
+ #require 'generator'
2
+
3
+ class GeneratorCacheArr < Array
4
+ def initialize(gen_spec=nil)
5
+ if !gen_spec
6
+ @gen_func = Proc.new
7
+ elsif gen_spec.kind_of?(Proc) || gen_spec.kind_of?(Method)
8
+ @gen_func = gen_spec
9
+ else
10
+ @gen_func = gen_spec.method("each")
11
+ end
12
+ @end = false
13
+ @next_lm = nil
14
+ super()
15
+ self.rewind
16
+ end
17
+
18
+ def end?
19
+ @end
20
+ end
21
+
22
+ def next?
23
+ !@end
24
+ end
25
+
26
+ def rewind
27
+ callcc { |@ret|
28
+ @gen_func.call { |lm|
29
+ callcc { |@next_lm| @ret.call }
30
+ self << lm
31
+ }
32
+ @end = true
33
+ @next_lm = proc {
34
+ raise EOFError, "no more elements available" }
35
+ @ret.call
36
+ }
37
+ self.clear
38
+ end
39
+
40
+ def next
41
+ callcc { |@ret| @next_lm.call }
42
+ self.last
43
+ end
44
+
45
+ def current
46
+ self.last
47
+ end
48
+
49
+ def index
50
+ self.length - 1
51
+ end
52
+
53
+ def cache_upto(last_i)
54
+ if last_i
55
+ self.length.upto(last_i) {
56
+ return if @end
57
+ self.next
58
+ }
59
+ else
60
+ while !@end
61
+ self.next
62
+ end
63
+ end
64
+ end
65
+
66
+ def [](*args)
67
+ if args.length == 1
68
+ i = args[0]
69
+ if i.kind_of? Range
70
+ if i.first < 0
71
+ last_i = nil
72
+ elsif i.last >= i.first
73
+ last_i = i.last + (i.exclude_end? ? 0:1)
74
+ else
75
+ if i.last + (i.exclude_end? ? 0:-1) < 0
76
+ last_i = nil
77
+ else
78
+ last_i = i.first
79
+ end
80
+ end
81
+ elsif i.kind_of? Array
82
+ last_i = i.max
83
+ elsif i.kind_of? Integer
84
+ if i < 0
85
+ last_i = nil
86
+ else
87
+ last_i = i
88
+ end
89
+ else
90
+ raise ArgumentError,
91
+ "Wrong single argument: #{i.inspect}"
92
+ end
93
+ elsif args.length == 2
94
+ last_i = args[0] + args[1] - 1
95
+ else
96
+ raise ArgumentError,
97
+ "Wrong numbef of arguments: #{args.inspect}"
98
+ end
99
+ self.cache_upto(last_i)
100
+ super(*args)
101
+ end
102
+ end
103
+
104
+ =begin
105
+ class GeneratorCacheArr < Generator
106
+ def initialize(*args, &block)
107
+ @arr = []
108
+ super(*args, &block)
109
+ end
110
+
111
+ def cache_upto(last_i)
112
+ if last_i
113
+ self.index.upto(last_i) {
114
+ return if self.end?
115
+ @arr << self.next
116
+ }
117
+ else
118
+ while !self.end?
119
+ @arr << self.next
120
+ end
121
+ end
122
+ end
123
+
124
+ def [](*args)
125
+ if args.length == 1
126
+ i = args[0]
127
+ if i.kind_of? Range
128
+ if i.first < 0
129
+ last_i = nil
130
+ elsif i.last >= i.first
131
+ last_i = i.last + (i.exclude_end? ? 0:1)
132
+ else
133
+ if i.last + (i.exclude_end? ? 0:-1) < 0
134
+ last_i = nil
135
+ else
136
+ last_i = i.first
137
+ end
138
+ end
139
+ elsif i.kind_of? Array
140
+ last_i = i.max
141
+ elsif i.kind_of? Integer
142
+ if i < 0
143
+ last_i = -i-1
144
+ else
145
+ last_i = i
146
+ end
147
+ else
148
+ raise ArgumentError,
149
+ "Wrong single argument: #{i.inspect}"
150
+ end
151
+ elsif args.length == 2
152
+ last_i = args[0] + args[1] - 1
153
+ else
154
+ raise ArgumentError,
155
+ "Wrong numbef of arguments: #{args.inspect}"
156
+ end
157
+ self.cache_upto(last_i)
158
+ @arr[*args]
159
+ end
160
+
161
+ def []=(*args)
162
+ @arr.[]=(*args)
163
+ end
164
+ end
165
+ =end
@@ -0,0 +1,602 @@
1
+ require 'pav/pix'
2
+ require 'pav/heap'
3
+ require 'pav/collection/std'
4
+
5
+ module PGraph
6
+
7
+ class NoReversePathwayError < RuntimeError
8
+ attr_accessor :pathway, :start_node
9
+
10
+ def initialize(pathway, start_node=nil)
11
+ @pathway = pathway
12
+ @start_node = start_node
13
+ end
14
+ end
15
+
16
+ class NoReverseLinkError < NoReversePathwayError
17
+ end
18
+
19
+ class NoReverseConnError < NoReversePathwayError
20
+ end
21
+
22
+ class NodeLink
23
+ attr_reader :node, :conn_k, :c_reverse
24
+
25
+ def initialize(node, conn_k)
26
+ @node = node
27
+ @conn_k = conn_k
28
+ @c_reverse = nil
29
+ end
30
+
31
+ def ==(link)
32
+ @node.node_eql?(link.node) && @conn_k == link.conn_k
33
+ end
34
+
35
+ def reverse
36
+ return @c_reverse if @c_reverse
37
+ conn = @node.conns[@conn_k]
38
+ exit = conn.exit
39
+ r_conn = conn.reverse(@node)
40
+ exit.conns.each_key_value { |cn_k, cn|
41
+ if cn == r_conn
42
+ return @c_reverse = NodeLink.new(exit, cn_k)
43
+ end
44
+ }
45
+ raise NoReverseLinkError.new(self, @node),
46
+ #"#{self.class.name}.reverse: No rev. link: " +
47
+ "#{self}; conn.: #{node.conns[@conn_k]}; r_conn: #{r_conn}" +
48
+ (exit.conns.length < 50 ? '; '+NodeConn.conns_to_s(
49
+ exit.conns) : '')
50
+ nil
51
+ end
52
+
53
+ def exit
54
+ @node.conns[@conn_k].exit
55
+ end
56
+
57
+ def length
58
+ @node.conns[@conn_k].length
59
+ end
60
+
61
+ def path
62
+ @node.conns[@conn_k].path
63
+ end
64
+
65
+ def conn
66
+ @node.conns[@conn_k]
67
+ end
68
+
69
+ def to_s(how=0)
70
+ "#{@node}-[#{@conn_k}]->" + (how >= 1 ?
71
+ @node.conns[@conn_k].exit.to_s : '')
72
+ end
73
+ end
74
+
75
+ class NodePath < Array
76
+ def ==(path2)
77
+ #$PDbgLog.sig_call(self.name + "#")
78
+ #$PDbgLog.puts_msg "self: #{self}; path2: #{path2}"
79
+ if self.length != path2.length
80
+ # $PDbgLog.sig_return
81
+ return false
82
+ end
83
+ self.each_with_index { |link, i|
84
+ return false if !link = path2.at(i) }
85
+ #$PDbgLog.sig_return
86
+ true
87
+ end
88
+
89
+ def +(path2)
90
+ self.dup.concat(path2)
91
+ end
92
+
93
+ def get_length
94
+ res = 0
95
+ self.each { |link| res += link.length }
96
+ res
97
+ end
98
+
99
+ def entry
100
+ return nil if self.empty?
101
+ self.first.node
102
+ end
103
+
104
+ def exit
105
+ return nil if self.empty?
106
+ self.last.exit
107
+ end
108
+
109
+ alias_method :reverse_links, :reverse
110
+ alias_method :reverse_links!, :reverse!
111
+
112
+ def reverse
113
+ res = []
114
+ self.each_with_index { |link, i|
115
+ res[self.length-i] = link.reverse }
116
+ end
117
+
118
+ def reverse!
119
+ 0.upto(self.length-1) { |i| self[i] = self[i].reverse }
120
+ super
121
+ end
122
+
123
+ def to_s(how=1)
124
+ self.join(' ') << (how > 0 ? self.exit.to_s : '')
125
+ end
126
+
127
+ def each_node
128
+ for link in self
129
+ yield(link.node)
130
+ end
131
+ if (exit = self.exit)
132
+ yield(exit)
133
+ end
134
+ end
135
+ end
136
+
137
+ class NodeConn
138
+ attr_reader :exit, :length
139
+ attr_accessor :path
140
+
141
+ def self.conns_to_s(conns)
142
+ conns.collect {|cn| cn.to_s}.join(', ')
143
+ end
144
+
145
+ def initialize(exit, length)
146
+ @exit = exit
147
+ @length = length
148
+ raise ArgumentError, "Conn.'s exit must be a Node!" unless
149
+ @exit.kind_of?(Node)
150
+ raise ArgumentError, "Conn.'s length must be numeric!" unless
151
+ @length.kind_of?(Numeric)
152
+ end
153
+
154
+ def reverse(conn_0)
155
+ res = NodeConn.new(conn_0, length)
156
+ res.path = path.reverse
157
+ res
158
+ end
159
+
160
+ def max_depth(to_parent_conn_k, visited={})
161
+ return @c_max_depth if @c_max_depth
162
+ @c_max_depth = @length +
163
+ @exit.dir_max_depth(to_parent_conn_k, visited)
164
+ end
165
+
166
+ def to_s(how=0)
167
+ "<-#{@length}->#{@exit}" + (how<1 ? '' : ': ' + self.path.to_s)
168
+ end
169
+
170
+ def eql?(conn)
171
+ @exit.node_eql?(conn.exit) && @length == conn.length &&
172
+ @path == conn.path
173
+ end
174
+
175
+ alias_method :==, :eql?
176
+ end
177
+
178
+ class Node
179
+ attr_reader :data, :conns, :c_rev_conns
180
+ attr_accessor :parent
181
+
182
+ def initialize(data, conns)
183
+ @data = data
184
+ @conns = conns
185
+ @c_rev_conns = conns.class.new
186
+ end
187
+
188
+ def rev_conn_key(conn_k)
189
+ if (tmp = @c_rev_conns[conn_k])
190
+ return tmp
191
+ end
192
+ conn = @conns[conn_k]
193
+ l = conn.exit
194
+ rev_conn = conn.reverse(self)
195
+ l.conns.each_key_value { |cn_k, cn|
196
+ return cn_k if cn == rev_conn }
197
+ raise NoReverseConnError.new(conn, self),
198
+ "#{self.coords_to_s} #{@conns[conn_k].to_s(2)}!"
199
+ nil
200
+ end
201
+
202
+ def to_parent_conn_key(conn_k)
203
+ begin
204
+ self.rev_conn_key(conn_k)
205
+ rescue NoReverseConnError
206
+ if self.node_eql?(@conns[conn_k].exit)
207
+ @c_rev_conns[conn_k] = conn_k
208
+ else
209
+ raise
210
+ end
211
+ end
212
+ end
213
+
214
+ def clear_rev_conns_cache
215
+ @c_rev_conns.clear
216
+ end
217
+
218
+ def delete_conn(conn_k)
219
+ @conns.delete_key(conn_k)
220
+ @c_rev_conns.delete_key(conn_k)
221
+ end
222
+
223
+ def conns_to_s
224
+ NodeConn.conns_to_s(@conns)
225
+ end
226
+
227
+ def eql?(node)
228
+ @data.eql?(node.data)
229
+ end
230
+
231
+ alias_method :node_eql?, :eql?
232
+
233
+ def hash
234
+ @data.hash
235
+ end
236
+
237
+ def each_link
238
+ @conns.each_key { |conn_k| yield(NodeLink.new(self, conn_k)) }
239
+ end
240
+
241
+ def get_min_lp_n_len(max_len=1.0/0.0)
242
+ #$PDbgLog.sig_call(self)
243
+ #$PDbgLog.print_msg self.coords_to_s + ", max_len=#{max_len}: "
244
+ p1, p2, len = *PSearch.first_norep_loop(self, max_len, max_len,
245
+ proc { |p| p.data }) { |node, lev|
246
+ res = []
247
+ node.conns.each_key_value { |cn_k, cn|
248
+ res << [cn.exit,NodeLink.new(node,cn_k),lev+cn.length] }
249
+ res
250
+ }
251
+ unless p1
252
+ #$PDbgLog.sig_return
253
+ return [nil, nil]
254
+ end
255
+ #$PDbgLog.puts_msg 'p1: ' + p1.collect { |link|
256
+ # link ? link.to_s(1) : link.inspect }.join(' ')
257
+ #$PDbgLog.puts_msg 'p2: ' + p2.collect { |link|
258
+ # link ? link.to_s(1) : link.inspect }.join(' ')
259
+ lp = NodePath.new
260
+ p2.reverse_each { |link| lp << link }
261
+ p1.each { |link| lp << link.reverse }
262
+ #$PDbgLog.sig_return(lp)
263
+ [lp, len]
264
+ end
265
+
266
+ def dup_with_map(map)
267
+ if (tmp = map[self])
268
+ return tmp
269
+ end
270
+ res = map[self] = Node.new(@data, conns=@conns.class.new)
271
+ @conns.each { |conn|
272
+ new_conn = NodeConn.new(conn.exit.dup_with_map(map),
273
+ conn.length)
274
+ new_conn.path = conn.path
275
+ conns << new_conn
276
+ }
277
+ res
278
+ end
279
+
280
+ def dup_graph
281
+ self.dup_with_map({})
282
+ end
283
+
284
+ def conn_max_depth(conn_k)
285
+ begin
286
+ rev_conn_k = self.rev_conn_key(conn_k)
287
+ rescue NoReversePathwayError
288
+ rev_conn_k = nil
289
+ end
290
+ @conns[conn_k].max_depth(rev_conn_k)
291
+ end
292
+
293
+ def dir_max_depth(to_parent_conn_k, visited)
294
+ #$PDbgLog.sig_call(self)
295
+ max_depth = 0
296
+ visited[self] = true
297
+ @conns.each_key_value { |conn_k, conn|
298
+ next if to_parent_conn_k == conn_k
299
+ if visited.include?(conn.exit)
300
+ max_depth = 1.0/0.0
301
+ break
302
+ end
303
+ tmp = conn.max_depth(self.rev_conn_key(conn_k), visited)
304
+ max_depth = tmp if tmp > max_depth
305
+ }
306
+ #$PDbgLog.sig_return
307
+ max_depth
308
+ end
309
+
310
+ def graph_each_conn_k(visited={}, &block)
311
+ if visited.include?(self)
312
+ vis_conns = visited[self]
313
+ else
314
+ vis_conns = visited[self] = @conns.class.new
315
+ end
316
+ @conns.each_key_value { |conn_k, conn|
317
+ unless vis_conns[conn_k]
318
+ yield(self, conn_k)
319
+ vis_conns[conn_k] = true
320
+ begin
321
+ visited[conn.exit] = conn.exit.conns.class.new unless
322
+ visited.include?(conn.exit)
323
+ visited[conn.exit][self.rev_conn_key(conn_k)] = true
324
+ rescue NoReversePathwayError
325
+ end
326
+ conn.exit.graph_each_conn_k(visited, &block)
327
+ end
328
+ }
329
+ end
330
+
331
+ def graph_each_node(visited={}, &block)
332
+ return if visited.include?(self)
333
+ visited[self] = true
334
+ yield(self)
335
+ @conns.each {|conn| conn.exit.graph_each_node(visited, &block) }
336
+ end
337
+
338
+ def to_s(how=0)
339
+ res = @data.to_s
340
+ return res if how < 1
341
+ res.concat('+conns: ')
342
+ @conns.each_key_value { |conn_k, conn|
343
+ res.concat("[#{conn_k}]#{conn.to_s(how-1)}; ")
344
+ }
345
+ res[-2,2] = ''
346
+ res
347
+ end
348
+
349
+ def graph_to_s
350
+ res = ''
351
+ self.graph_each_conn_k { |node, conn_k|
352
+ res.concat(node.to_s + ": [#{conn_k}]#{node.conns[
353
+ conn_k].to_s(2)}\n")
354
+ }
355
+ res
356
+ end
357
+ end
358
+
359
+ class NodeCalcPCachePathIter
360
+ attr_accessor :path_cache, :node
361
+
362
+ def initialize(path_cache=nil, node=nil)
363
+ @path_cache = path_cache
364
+ @node = node
365
+ end
366
+
367
+ def pop
368
+ to_link = path_cache[@node][1]
369
+ @node = to_link ? to_link.node : nil
370
+ to_link
371
+ end
372
+ end
373
+
374
+ class NodeCalc
375
+ attr_reader :node, :c_paths
376
+ attr_accessor :link_filter
377
+
378
+ def initialize(node)
379
+ @node = node
380
+ @c_paths = {}
381
+ @link_filter = nil
382
+ end
383
+
384
+ def find_shortest_path_to_node(dest, max_lev=1.0/0.0,
385
+ path_cache=@c_paths)
386
+ #$PDbgLog.sig_call(self)
387
+ if max_lev < 0
388
+ #$PDbgLog.sig_return("max_lev < 0: nil")
389
+ return nil
390
+ end
391
+ path_cache = {} unless path_cache
392
+ if @link_filter
393
+ #$PDbgLog.sig_return
394
+ return self.find_shortest_path_to_node_with_link_filter(
395
+ dest, max_lev, path_cache)
396
+ end
397
+ path_cache[@node] = [0, nil] unless path_cache.include?(@node)&&
398
+ path_cache[@node][0] <= 0 && path_cache[@node][1] == nil
399
+ tail = PMinHeap.new { |a,b| a[1] <=> b[1] }
400
+ path_cache.each_pair { |node, frm| tail.push([node, frm[0]]) }
401
+ while !tail.empty?
402
+ node, lev = *tail.pop
403
+ next if path_cache.include?(node) &&
404
+ path_cache[node][0] < lev
405
+ if path_cache.include?(dest)
406
+ res = NodePath.new; node = dest
407
+ to_link = path_cache[node][1]
408
+ while to_link
409
+ res << to_link
410
+ to_link = path_cache[to_link.node][1]
411
+ end
412
+ res.reverse_links!
413
+ #$PDbgLog.sig_return(res.inspect)
414
+ return res
415
+ end
416
+ node.conns.each_key_value { |conn_k,conn| l = conn.exit
417
+ if (l_lev = lev+conn.length) <= max_lev &&
418
+ (!path_cache.include?(l) || path_cache[l][0] > l_lev)
419
+ tail.push([l, l_lev])
420
+ path_cache[l]=[l_lev,NodeLink.new(node,conn_k)]
421
+ end
422
+ }
423
+ end
424
+ #$PDbgLog.sig_return("nil")
425
+ nil
426
+ end
427
+
428
+ def find_shortest_path_to_node_with_link_filter(dest, max_lev,
429
+ path_cache)
430
+ #$PDbgLog.sig_call(self)
431
+ path_cache[@node] = [0, nil] unless path_cache.include?(@node)&&
432
+ path_cache[@node][0] <= 0 && path_cache[@node][1] == nil
433
+ tail = PMinHeap.new { |a,b| a[1] <=> b[1] }
434
+ path_cache.each_pair { |node, frm| tail.push([node, frm[0]]) }
435
+ #$PDbgLog.print_msg "node#{@node.coords_to_s}, dest#{dest.
436
+ # coords_to_s}, max_lev=#{max_lev}: "
437
+ while !tail.empty?
438
+ node, lev = *tail.pop
439
+ # $PDbgLog.print_msg "node#{node.coords_to_s},lev=#{lev} "
440
+ next if path_cache.include?(node) &&
441
+ path_cache[node][0] < lev
442
+ if path_cache.include?(dest)
443
+ res = NodePath.new; node = dest
444
+ to_link = path_cache[node][1]
445
+ while to_link
446
+ res << to_link
447
+ to_link = path_cache[to_link.node][1]
448
+ end
449
+ res.reverse_links!
450
+ #$PDbgLog.sig_return('found ' + res.to_s + '.')
451
+ return res
452
+ end
453
+ node.conns.each_key_value { |conn_k,conn| l = conn.exit
454
+ #$PDbgLog.print_msg "conn #{conn_k}: #{conn} "
455
+ if (l_lev = lev+conn.length) <= max_lev &&
456
+ (!path_cache.include?(l) || path_cache[l][0]>l_lev) &&
457
+ @link_filter.call(link=NodeLink.new(node,conn_k))
458
+ tail.push([l, l_lev])
459
+ path_cache[l]=[l_lev, link]
460
+ end
461
+ }
462
+ end
463
+ #$PDbgLog.sig_return("no path found.")
464
+ nil
465
+ end
466
+
467
+ def self.path_cache_to_s(path_cache)
468
+ "{#{path_cache.keys.to_a.sort.collect{|k| k.to_s + "=>[#{
469
+ path_cache[k][0]}, " + (path_cache[k][1] ?
470
+ path_cache[k][1].to_s : 'nil') + "]"}.join(", ")}}"
471
+ end
472
+
473
+ def self.path_cache_get_path_to_self(node, path_cache)
474
+ to_link = path_cache[node][1]
475
+ res = NodePath.new
476
+ while !to_link.node.node_eql?(node)
477
+ res << to_link
478
+ to_link = path_cache[to_link.node]
479
+ end
480
+ res << to_link
481
+ res.reverse_links!
482
+ end
483
+
484
+ def self.path_cache_get_path(node, path_cache)
485
+ #$PDbgLog.sig_call(self)
486
+ #$PDbgLog.print_msg "node#{node}, path_cache: #{self.
487
+ # path_cache_to_s(path_cache)}: "
488
+ to_link = path_cache[node][1]
489
+ res = NodePath.new
490
+ while to_link
491
+ res << to_link
492
+ to_link = path_cache[to_link.node][1]
493
+ end
494
+ res.reverse_links!
495
+ #$PDbgLog.sig_return(res.to_s(1))
496
+ res
497
+ end
498
+
499
+ def find_first_path_to(dest, max_lev=1.0/0.0, path_cache=nil)
500
+ if max_lev < 0
501
+ return nil
502
+ end
503
+ if @link_filter
504
+ return self.find_first_path_to_with_link_filter(dest,
505
+ max_lev, path_cache)
506
+ end
507
+ if dest.kind_of?(Proc)
508
+ dest_proc = dest
509
+ else
510
+ dest_proc = proc {|node,lev| dest.node_eql?(node)}
511
+ end
512
+ tail = PMinHeap.new { |frm1,frm2| frm1[1] <=> frm2[1] }
513
+ unless path_cache
514
+ path_cache = @c_paths
515
+ unless dest.kind_of?(Proc)
516
+ return NodeCalc.path_cache_get_path(dest,
517
+ path_cache) if path_cache.include?(dest)
518
+ end
519
+ path_cache.each_pair { |node, frm|
520
+ tail.push([node, frm[0]]) }
521
+ end
522
+ path_cache[@node] = [0, nil]
523
+ tail.push([@node, 0])
524
+ while !tail.empty?
525
+ node, lev = *tail.pop
526
+ next if path_cache.include?(node) &&
527
+ path_cache[node][0] < lev
528
+ if dest_proc.call(node, lev)
529
+ res = NodeCalc.path_cache_get_path(node,
530
+ path_cache)
531
+ return res
532
+ end
533
+ node.conns.each_key_value { |conn_k,conn| l = conn.exit
534
+ if (l_lev = lev + conn.length) <= max_lev &&
535
+ (!path_cache.include?(l) || path_cache[l][0] > l_lev)
536
+ tail.push([l, l_lev])
537
+ path_cache[l]=[l_lev,NodeLink.new(node,conn_k)]
538
+ end
539
+ }
540
+ end
541
+ nil
542
+ end
543
+
544
+ def find_first_path_to_with_link_filter(dest, max_lev, path_cache=nil)
545
+ #$PDbgLog.sig_call(self)
546
+ #$PDbgLog.print_msg "dest:#{dest}, max_lev=#{max_lev}"
547
+ if dest.kind_of?(Proc)
548
+ dest_proc = dest
549
+ else
550
+ dest_proc = proc {|node,lev| dest.node_eql?(node)}
551
+ end
552
+ tail = PMinHeap.new { |frm1,frm2| frm1[1] <=> frm2[1] }
553
+ unless path_cache
554
+ path_cache = @c_paths
555
+ if !dest.kind_of?(Proc) && path_cache.include?(dest)
556
+ #$PDbgLog.sig_return(': cached.')
557
+ return NodeCalc.path_cache_get_path(dest,
558
+ path_cache)
559
+ end
560
+ path_cache.each_pair { |node, frm|
561
+ tail.push([node, frm[0]]) }
562
+ end
563
+ path_cache[@node] = [0, nil]
564
+ tail.push([@node, 0])
565
+ while !tail.empty?
566
+ node, lev = *tail.pop
567
+ next if path_cache.include?(node) &&
568
+ path_cache[node][0] < lev
569
+ #$PDbgLog.print_msg "node#{node},lev=#{lev} "
570
+ if dest_proc.call(node, lev)
571
+ res = NodeCalc.path_cache_get_path(node,
572
+ path_cache)
573
+ #$PDbgLog.sig_return('Done.')
574
+ return res
575
+ end
576
+ node.conns.each_key_value { |conn_k,conn| l = conn.exit
577
+ if (l_lev = lev + conn.length) <= max_lev &&
578
+ (!path_cache.include?(l) || path_cache[l][0]>l_lev) &&
579
+ @link_filter.call(link=NodeLink.new(node,conn_k))
580
+ tail.push([l, l_lev])
581
+ path_cache[l] = [l_lev, link]
582
+ end
583
+ }
584
+ end
585
+ #$PDbgLog.sig_return(': nil')
586
+ nil
587
+ end
588
+
589
+ def kill_path_cache!
590
+ @c_paths.clear
591
+ end
592
+
593
+ def path_cache_each_path
594
+ iter = NodeCalcPCachePathIter.new(@c_paths)
595
+ @c_paths.each_key { |node|
596
+ iter.node = node
597
+ yield(iter)
598
+ }
599
+ end
600
+ end
601
+
602
+ end