contrek 1.3.3 → 1.3.4
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +3 -1
- data/README.md +28 -28
- data/contrek.gemspec +1 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/ContrekApi.h +2 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/Tests.cpp +0 -2
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/FinderUtils.cpp +11 -5
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.cpp +8 -10
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/Node.h +4 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.cpp +114 -42
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/NodeCluster.h +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/PolygonFinder.h +2 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cluster.cpp +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.cpp +66 -116
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Cursor.h +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Finder.cpp +1 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.cpp +2 -87
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Part.h +1 -13
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/PartPool.cpp +0 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.cpp +1 -57
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Partitionable.h +1 -4
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Queueable.h +31 -17
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.cpp +0 -16
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Sequence.h +0 -9
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/finder/concurrent/Tile.cpp +1 -1
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/DouglasPeuckerReducer.cpp +177 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/DouglasPeuckerReducer.h +52 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/RasterReducer.cpp +109 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/RasterReducer.h +32 -0
- data/ext/cpp_polygon_finder/PolygonFinder/src/polygon/reducers/VisvalingamReducer.h +6 -1
- data/ext/cpp_polygon_finder/cpp_polygon_finder.cpp +4 -0
- data/lib/contrek/bitmaps/painting.rb +27 -10
- data/lib/contrek/bitmaps/png_bitmap.rb +3 -0
- data/lib/contrek/bitmaps/raw_bitmap.rb +1 -0
- data/lib/contrek/bitmaps/rendering.rb +74 -0
- data/lib/contrek/finder/concurrent/cursor.rb +62 -84
- data/lib/contrek/finder/concurrent/finder.rb +2 -1
- data/lib/contrek/finder/concurrent/part.rb +4 -77
- data/lib/contrek/finder/concurrent/partitionable.rb +1 -58
- data/lib/contrek/finder/concurrent/queueable.rb +23 -5
- data/lib/contrek/finder/concurrent/sequence.rb +0 -15
- data/lib/contrek/finder/concurrent/tile.rb +1 -1
- data/lib/contrek/finder/node.rb +26 -8
- data/lib/contrek/finder/node_cluster.rb +91 -37
- data/lib/contrek/finder/polygon_finder.rb +1 -1
- data/lib/contrek/reducers/douglas_peucker_reducer.rb +191 -0
- data/lib/contrek/reducers/raster_reducer.rb +72 -0
- data/lib/contrek/version.rb +1 -1
- data/lib/contrek.rb +3 -0
- metadata +23 -2
|
@@ -51,24 +51,15 @@ module Contrek
|
|
|
51
51
|
if part.innerable?
|
|
52
52
|
all_parts = []
|
|
53
53
|
tracked_end_points = []
|
|
54
|
-
|
|
55
|
-
traverse_inner(part, all_parts, bounds, tracked_end_points)
|
|
56
|
-
range_of_bounds = (bounds[:min]..bounds[:max])
|
|
57
|
-
|
|
54
|
+
traverse_inner(part, all_parts, tracked_end_points)
|
|
58
55
|
retme_sequence = Sequence.new
|
|
59
56
|
all_parts.each do |part|
|
|
60
57
|
part.touch!
|
|
61
|
-
retme_sequence.
|
|
62
|
-
next false if part.is?(Part::ADDED) && !(range_of_bounds === position.payload[:y])
|
|
63
|
-
|
|
64
|
-
!(polyline.tile.tg_border?(position.payload) && position.end_point.tracked_outer)
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
if retme_sequence.is_not_vertical
|
|
68
|
-
inner_polyline = InnerPolyline.new(sequence: retme_sequence)
|
|
69
|
-
return_inner_polylines << inner_polyline
|
|
70
|
-
mark_children(tracked_end_points, polyline, inner_polyline) if treemap
|
|
58
|
+
retme_sequence.append(part)
|
|
71
59
|
end
|
|
60
|
+
inner_polyline = InnerPolyline.new(sequence: retme_sequence)
|
|
61
|
+
return_inner_polylines << inner_polyline
|
|
62
|
+
mark_children(tracked_end_points, polyline, inner_polyline) if treemap
|
|
72
63
|
end
|
|
73
64
|
end
|
|
74
65
|
shape_index += 1
|
|
@@ -78,76 +69,55 @@ module Contrek
|
|
|
78
69
|
|
|
79
70
|
private
|
|
80
71
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# rubocop:disable Lint/NonLocalExitFromIterator
|
|
99
|
-
def traverse_outer(act_part, all_parts, shapes_sequence, outer_joined_polyline)
|
|
100
|
-
last_part = all_parts.last
|
|
101
|
-
all_parts << act_part if last_part != act_part
|
|
102
|
-
if act_part.is?(Part::EXCLUSIVE)
|
|
103
|
-
return if act_part.size == 0
|
|
104
|
-
while (position = act_part.next_position)
|
|
105
|
-
outer_joined_polyline.add(position)
|
|
106
|
-
end
|
|
107
|
-
else
|
|
108
|
-
return if act_part.dead_end && all_parts.size > 1 && last_part.is?(Part::SEAM) && last_part.polyline == act_part.polyline
|
|
109
|
-
while (new_position = act_part.iterator)
|
|
110
|
-
return if outer_joined_polyline.size > 1 &&
|
|
111
|
-
outer_joined_polyline.head.payload == new_position.payload &&
|
|
112
|
-
act_part == all_parts.first
|
|
113
|
-
outer_joined_polyline.add(Position.new(position: new_position.payload, hub: @cluster.hub))
|
|
114
|
-
new_position.end_point.tracked_outer = true
|
|
115
|
-
versus = act_part.versus
|
|
116
|
-
part = new_position.end_point.queues.find do |p|
|
|
117
|
-
(p.mirror || act_part.mirror || p.versus == -versus) && p.polyline.tile != act_part.polyline.tile
|
|
72
|
+
def traverse_outer(start_part, all_parts, shapes_sequence, outer_joined_polyline)
|
|
73
|
+
act_part = start_part
|
|
74
|
+
|
|
75
|
+
while act_part
|
|
76
|
+
last_part = all_parts.last
|
|
77
|
+
all_parts << act_part if last_part != act_part
|
|
78
|
+
jumped_to_new_part = false
|
|
79
|
+
if act_part.is?(Part::EXCLUSIVE)
|
|
80
|
+
return if act_part.size == 0
|
|
81
|
+
while (position = act_part.next_position)
|
|
82
|
+
outer_joined_polyline.add(position)
|
|
118
83
|
end
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
84
|
+
else
|
|
85
|
+
while (new_position = act_part.iterator)
|
|
86
|
+
if outer_joined_polyline.size > 1 &&
|
|
87
|
+
outer_joined_polyline.head.payload == new_position.payload &&
|
|
88
|
+
act_part == all_parts.first
|
|
89
|
+
return
|
|
90
|
+
end
|
|
91
|
+
new_position.end_point.tracked_outer = true
|
|
92
|
+
versus = act_part.versus
|
|
93
|
+
part = new_position.end_point.queues.find do |p|
|
|
94
|
+
(p.versus == -versus) && p.polyline.tile != act_part.polyline.tile
|
|
95
|
+
end
|
|
96
|
+
if part
|
|
97
|
+
if all_parts[-2] != part
|
|
98
|
+
if !shapes_sequence.include?(part.polyline.shape)
|
|
99
|
+
shapes_sequence << part.polyline.shape
|
|
100
|
+
end
|
|
128
101
|
part.next_position(new_position)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
102
|
+
act_part = part
|
|
103
|
+
jumped_to_new_part = true
|
|
104
|
+
break
|
|
132
105
|
end
|
|
133
106
|
end
|
|
107
|
+
act_part.next_position
|
|
134
108
|
end
|
|
135
|
-
act_part.next_position
|
|
136
109
|
end
|
|
110
|
+
next if jumped_to_new_part
|
|
111
|
+
next_part = act_part.circular_next
|
|
112
|
+
next_part.rewind!
|
|
113
|
+
act_part = next_part
|
|
137
114
|
end
|
|
138
|
-
next_part = act_part.circular_next
|
|
139
|
-
next_part.rewind!
|
|
140
|
-
traverse_outer(act_part.circular_next, all_parts, shapes_sequence, outer_joined_polyline)
|
|
141
115
|
end
|
|
142
116
|
|
|
143
|
-
|
|
117
|
+
# rubocop:disable Lint/NonLocalExitFromIterator
|
|
118
|
+
def traverse_inner(act_part, all_parts, tracked_end_points)
|
|
144
119
|
return if act_part == all_parts.first
|
|
145
120
|
|
|
146
|
-
if act_part.size > 0
|
|
147
|
-
min_y, max_y = act_part.to_a.minmax_by { |p| p[:y] }
|
|
148
|
-
bounds[:min] = [bounds[:min], min_y[:y]].min
|
|
149
|
-
bounds[:max] = [bounds[:max], max_y[:y]].max
|
|
150
|
-
end
|
|
151
121
|
if act_part.innerable?
|
|
152
122
|
all_parts << act_part
|
|
153
123
|
while (act_part = act_part.circular_next)
|
|
@@ -161,15 +131,6 @@ module Contrek
|
|
|
161
131
|
next if dest_part_versus != 0 && dest_part_versus == act_part.versus
|
|
162
132
|
|
|
163
133
|
tracked_end_points << act_part.head.end_point
|
|
164
|
-
|
|
165
|
-
link_seq = dest_part.continuum_to?(act_part)
|
|
166
|
-
if link_seq.any?
|
|
167
|
-
ins_part = Part.new(Part::ADDED, act_part.polyline)
|
|
168
|
-
link_seq.each do |pos|
|
|
169
|
-
ins_part.add(Position.new(position: nil, hub: nil, known_endpoint: pos))
|
|
170
|
-
end
|
|
171
|
-
all_parts << ins_part
|
|
172
|
-
end
|
|
173
134
|
shape = dest_part.polyline.shape
|
|
174
135
|
if !dest_part.polyline.on?(Polyline::TRACKED_OUTER)
|
|
175
136
|
@shapes_sequence << shape
|
|
@@ -179,7 +140,7 @@ module Contrek
|
|
|
179
140
|
dest_part.polyline.turn_on(Polyline::TRACKED_OUTER)
|
|
180
141
|
if !dest_part.touched
|
|
181
142
|
dest_part.touch!
|
|
182
|
-
traverse_inner(dest_part.circular_next, all_parts,
|
|
143
|
+
traverse_inner(dest_part.circular_next, all_parts, tracked_end_points)
|
|
183
144
|
return
|
|
184
145
|
end
|
|
185
146
|
end
|
|
@@ -188,10 +149,27 @@ module Contrek
|
|
|
188
149
|
end
|
|
189
150
|
end
|
|
190
151
|
elsif act_part.next
|
|
191
|
-
traverse_inner(act_part.next, all_parts,
|
|
152
|
+
traverse_inner(act_part.next, all_parts, tracked_end_points)
|
|
192
153
|
end
|
|
193
154
|
end
|
|
194
155
|
# rubocop:enable Lint/NonLocalExitFromIterator
|
|
156
|
+
|
|
157
|
+
# finds each part (and relative polyline) inscribed between two end_points and sets the
|
|
158
|
+
# founded inner_polyline which be later used to define in which parent hole is placed.
|
|
159
|
+
def mark_children(end_points, outer_polyline, inner_polyline)
|
|
160
|
+
end_points.each_slice(2) do |a, b|
|
|
161
|
+
range = [a.position[:y], b.position[:y]].sort
|
|
162
|
+
(range[0] + 1).upto(range[1] - 1) do |y|
|
|
163
|
+
if (end_point = @cluster.hub.payloads[y])
|
|
164
|
+
end_point.queues.each do |part|
|
|
165
|
+
if part.polyline != outer_polyline
|
|
166
|
+
part.polyline.inside_inner_polyline = inner_polyline
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
195
173
|
end
|
|
196
174
|
end
|
|
197
175
|
end
|
|
@@ -93,7 +93,8 @@ module Contrek
|
|
|
93
93
|
compress: ((compress_time * 1000).round(3) if @options.has_key?(:compress))
|
|
94
94
|
}.compact,
|
|
95
95
|
width: @maximum_width,
|
|
96
|
-
height: @height
|
|
96
|
+
height: @height,
|
|
97
|
+
versus: options[:versus]
|
|
97
98
|
}
|
|
98
99
|
metadata[:treemap] = @whole_tile.compute_treemap if options[:treemap]
|
|
99
100
|
Contrek::Finder::Result.new(raw_polygons, metadata)
|
|
@@ -7,25 +7,16 @@ module Contrek
|
|
|
7
7
|
|
|
8
8
|
SEAM = 1
|
|
9
9
|
EXCLUSIVE = 0
|
|
10
|
-
ADDED = 2
|
|
11
10
|
|
|
12
11
|
attr_reader :polyline, :touched
|
|
13
|
-
attr_accessor :next, :circular_next, :
|
|
14
|
-
:trasmuted, :versus, :mirror, :next_seam, :transmutation_skip
|
|
12
|
+
attr_accessor :next, :circular_next, :type, :versus
|
|
15
13
|
def initialize(type, polyline)
|
|
16
14
|
@type = type
|
|
17
15
|
@polyline = polyline
|
|
18
16
|
@next = nil
|
|
19
|
-
@next_seam = nil
|
|
20
17
|
@circular_next = nil
|
|
21
|
-
@prev = nil
|
|
22
|
-
@dead_end = false
|
|
23
18
|
@touched = false
|
|
24
|
-
@inverts = false
|
|
25
|
-
@trasmuted = false
|
|
26
19
|
@versus = 0
|
|
27
|
-
@mirror = false
|
|
28
|
-
@transmutation_skip = false
|
|
29
20
|
end
|
|
30
21
|
|
|
31
22
|
def is?(type)
|
|
@@ -57,12 +48,11 @@ module Contrek
|
|
|
57
48
|
|
|
58
49
|
def name
|
|
59
50
|
{Part::EXCLUSIVE => "EXCLUSIVE",
|
|
60
|
-
Part::SEAM => "SEAM"
|
|
61
|
-
Part::ADDED => "ADDED"}[type]
|
|
51
|
+
Part::SEAM => "SEAM"}[type]
|
|
62
52
|
end
|
|
63
53
|
|
|
64
54
|
def inspect
|
|
65
|
-
"part #{polyline.parts.index(self)} (
|
|
55
|
+
"part #{polyline.parts.index(self)} (versus=#{@versus} touched=#{@touched}, #{size}x) of #{polyline.named} (#{name}) (#{to_a.map { |e| "[#{e[:x]},#{e[:y]}]" }.join})"
|
|
66
56
|
end
|
|
67
57
|
|
|
68
58
|
def innerable?
|
|
@@ -70,80 +60,17 @@ module Contrek
|
|
|
70
60
|
end
|
|
71
61
|
|
|
72
62
|
def orient!
|
|
73
|
-
@versus = if size <= 1
|
|
63
|
+
@versus = if size <= 1
|
|
74
64
|
0
|
|
75
65
|
else
|
|
76
66
|
diff = tail.payload[:y] - head.payload[:y]
|
|
77
67
|
if diff == 0
|
|
78
|
-
@mirror = true
|
|
79
68
|
0
|
|
80
69
|
else
|
|
81
70
|
diff.positive? ? 1 : -1
|
|
82
71
|
end
|
|
83
72
|
end
|
|
84
73
|
end
|
|
85
|
-
|
|
86
|
-
def try_transmutation!
|
|
87
|
-
head_queues = head.end_point.queues
|
|
88
|
-
return if head_queues.size == 1
|
|
89
|
-
other_head_part = head_queues.find { |part| part.polyline.tile == polyline.tile && part != self }
|
|
90
|
-
if other_head_part
|
|
91
|
-
tail_queues = tail.end_point.queues
|
|
92
|
-
if tail_queues.find { |part| part == other_head_part }
|
|
93
|
-
if (other_head_part.tail.payload[:y] == tail.payload[:y] && other_head_part.head.payload[:y] == head.payload[:y]) ||
|
|
94
|
-
(other_head_part.tail.payload[:y] == head.payload[:y] && other_head_part.head.payload[:y] == tail.payload[:y])
|
|
95
|
-
if self.next.nil? && other_head_part.prev.nil?
|
|
96
|
-
self.mirror = true
|
|
97
|
-
end
|
|
98
|
-
else
|
|
99
|
-
self.type = Part::EXCLUSIVE
|
|
100
|
-
self.trasmuted = true
|
|
101
|
-
other_head_part.transmutation_skip = true
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def within?(other)
|
|
108
|
-
self_min, self_max = [head.payload[:y], tail.payload[:y]].minmax
|
|
109
|
-
other_min, other_max = [other.head.payload[:y], other.tail.payload[:y]].minmax
|
|
110
|
-
self_min >= other_min && self_max <= other_max
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def same_length?(other)
|
|
114
|
-
(head.payload[:y] - tail.payload[:y]).abs ==
|
|
115
|
-
(other.head.payload[:y] - other.tail.payload[:y]).abs
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def continuum_to?(other)
|
|
119
|
-
return [] if size <= 2 && inverts && other.size <= 2 && other.inverts
|
|
120
|
-
return [] if other.head.nil?
|
|
121
|
-
|
|
122
|
-
target = other.head.payload
|
|
123
|
-
cursor = tail
|
|
124
|
-
while cursor
|
|
125
|
-
if cursor.payload == target
|
|
126
|
-
s = cursor
|
|
127
|
-
o = other.head
|
|
128
|
-
match = true
|
|
129
|
-
nodes = []
|
|
130
|
-
while s && o
|
|
131
|
-
if s.payload != o.payload
|
|
132
|
-
match = false
|
|
133
|
-
break
|
|
134
|
-
end
|
|
135
|
-
nodes << s.end_point
|
|
136
|
-
s = s.next
|
|
137
|
-
o = o.next
|
|
138
|
-
end
|
|
139
|
-
if match && s.nil?
|
|
140
|
-
return nodes
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
cursor = cursor.prev
|
|
144
|
-
end
|
|
145
|
-
[]
|
|
146
|
-
end
|
|
147
74
|
end
|
|
148
75
|
end
|
|
149
76
|
end
|
|
@@ -8,8 +8,6 @@ module Contrek
|
|
|
8
8
|
def initialize(*args, **kwargs, &block)
|
|
9
9
|
super
|
|
10
10
|
@parts = []
|
|
11
|
-
@first_seam = nil
|
|
12
|
-
@last_seam = nil
|
|
13
11
|
end
|
|
14
12
|
|
|
15
13
|
def add_part(new_part)
|
|
@@ -17,15 +15,7 @@ module Contrek
|
|
|
17
15
|
@parts << new_part
|
|
18
16
|
last.next = last.circular_next = new_part if last
|
|
19
17
|
new_part.circular_next = @parts.first
|
|
20
|
-
new_part.
|
|
21
|
-
if new_part.is?(Part::SEAM)
|
|
22
|
-
@first_seam ||= new_part
|
|
23
|
-
if !@last_seam.nil?
|
|
24
|
-
@last_seam.next_seam = new_part
|
|
25
|
-
end
|
|
26
|
-
@last_seam = new_part
|
|
27
|
-
new_part.orient!
|
|
28
|
-
end
|
|
18
|
+
new_part.orient! if new_part.is?(Part::SEAM)
|
|
29
19
|
end
|
|
30
20
|
|
|
31
21
|
def inspect_parts
|
|
@@ -35,8 +25,6 @@ module Contrek
|
|
|
35
25
|
def partition!
|
|
36
26
|
current_part = nil
|
|
37
27
|
@parts = []
|
|
38
|
-
@first_seam = nil
|
|
39
|
-
@last_seam = nil
|
|
40
28
|
|
|
41
29
|
@raw.each_with_index do |position, n|
|
|
42
30
|
if @tile.tg_border?(position)
|
|
@@ -52,54 +40,9 @@ module Contrek
|
|
|
52
40
|
add_part(current_part)
|
|
53
41
|
current_part = Part.new(Part::EXCLUSIVE, self)
|
|
54
42
|
end
|
|
55
|
-
if n > 0 && @raw[n - 1] == position
|
|
56
|
-
current_part.inverts = true
|
|
57
|
-
end
|
|
58
43
|
current_part.add_position(position)
|
|
59
44
|
end
|
|
60
45
|
add_part(current_part)
|
|
61
|
-
|
|
62
|
-
transmute_parts!
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
private
|
|
66
|
-
|
|
67
|
-
# If there are SEAM parts and one is canceled out by another within the same polyline,
|
|
68
|
-
# meaning that all its points are repeated in another, longer sequence,
|
|
69
|
-
# then the shorter one is converted to EXCLUSIVE and marked as transmuted
|
|
70
|
-
def transmute_parts!
|
|
71
|
-
transpose = tile.cluster.finder.transpose?
|
|
72
|
-
if (current_seam = @first_seam)
|
|
73
|
-
loop do
|
|
74
|
-
if transpose
|
|
75
|
-
transmute_transposed_part(current_seam)
|
|
76
|
-
elsif !current_seam.transmutation_skip
|
|
77
|
-
current_seam.try_transmutation!
|
|
78
|
-
end
|
|
79
|
-
current_seam = current_seam.next_seam
|
|
80
|
-
break if current_seam.nil?
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def transmute_transposed_part(part)
|
|
86
|
-
if (current_seam = @first_seam)
|
|
87
|
-
loop do
|
|
88
|
-
if current_seam != part
|
|
89
|
-
if part.within?(current_seam)
|
|
90
|
-
if !part.same_length?(current_seam)
|
|
91
|
-
part.type = Part::EXCLUSIVE
|
|
92
|
-
part.trasmuted = true
|
|
93
|
-
part.head.end_point.queues.delete(part)
|
|
94
|
-
part.tail.end_point.queues.delete(part)
|
|
95
|
-
return
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
current_seam = current_seam.next_seam
|
|
100
|
-
break if current_seam.nil?
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
46
|
end
|
|
104
47
|
end
|
|
105
48
|
end
|
|
@@ -47,12 +47,30 @@ module Contrek
|
|
|
47
47
|
node.after_add(self)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
def
|
|
51
|
-
queueable.
|
|
52
|
-
|
|
53
|
-
queueable
|
|
54
|
-
|
|
50
|
+
def append(queueable)
|
|
51
|
+
return if queueable.size.zero?
|
|
52
|
+
queueable.each do |node|
|
|
53
|
+
node.before_rem(queueable)
|
|
54
|
+
node.owner = self
|
|
55
55
|
end
|
|
56
|
+
if @tail
|
|
57
|
+
@tail.next = queueable.head
|
|
58
|
+
queueable.head.prev = @tail
|
|
59
|
+
else
|
|
60
|
+
@head = queueable.head
|
|
61
|
+
end
|
|
62
|
+
@tail = queueable.tail
|
|
63
|
+
@size += queueable.size
|
|
64
|
+
queueable.reset!
|
|
65
|
+
|
|
66
|
+
each { |node| node.after_add(self) }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def reset!
|
|
70
|
+
@head = nil
|
|
71
|
+
@tail = nil
|
|
72
|
+
@size = 0
|
|
73
|
+
@iterator = 0
|
|
56
74
|
end
|
|
57
75
|
|
|
58
76
|
# from yield: false => stop, true => continue
|
|
@@ -5,21 +5,6 @@ module Contrek
|
|
|
5
5
|
class Sequence
|
|
6
6
|
attr_accessor :shape
|
|
7
7
|
prepend Queueable
|
|
8
|
-
|
|
9
|
-
def is_not_vertical
|
|
10
|
-
return false if size < 2
|
|
11
|
-
x0 = head.payload[:x]
|
|
12
|
-
rewind!
|
|
13
|
-
while (position = iterator)
|
|
14
|
-
return true if position.payload[:x] != x0
|
|
15
|
-
forward!
|
|
16
|
-
end
|
|
17
|
-
false
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def get_vector_cache
|
|
21
|
-
@vector_cache ||= to_a
|
|
22
|
-
end
|
|
23
8
|
end
|
|
24
9
|
end
|
|
25
10
|
end
|
data/lib/contrek/finder/node.rb
CHANGED
|
@@ -6,7 +6,7 @@ module Contrek
|
|
|
6
6
|
include Listable
|
|
7
7
|
|
|
8
8
|
attr_reader :min_x, :max_x, :y, :name, :tangs_sequence, :tangs_count, :data_pointer,
|
|
9
|
-
:upper_start, :upper_end, :lower_start, :lower_end
|
|
9
|
+
:upper_start, :upper_end, :lower_start, :lower_end
|
|
10
10
|
attr_accessor :track, :abs_x_index, :outer_index, :inner_index, :inner_left_index, :inner_right_index
|
|
11
11
|
|
|
12
12
|
T_UP = -1
|
|
@@ -30,7 +30,7 @@ module Contrek
|
|
|
30
30
|
def initialize(cluster, min_x, max_x, y, name, connectivity_offset = 0)
|
|
31
31
|
@name = name
|
|
32
32
|
@min_x = min_x
|
|
33
|
-
@max_x = max_x
|
|
33
|
+
@max_x = max_x + 1
|
|
34
34
|
@y = y
|
|
35
35
|
@tangs_sequence = nil
|
|
36
36
|
@tangs_count = 0
|
|
@@ -47,12 +47,14 @@ module Contrek
|
|
|
47
47
|
@upper_end = -1
|
|
48
48
|
@lower_start = Float::INFINITY
|
|
49
49
|
@lower_end = -1
|
|
50
|
-
@start_point = {x: min_x, y: y}
|
|
51
|
-
@end_point = {x: max_x, y: y}
|
|
52
50
|
@cluster = cluster
|
|
53
51
|
cluster.add_node(self, connectivity_offset)
|
|
54
52
|
end
|
|
55
53
|
|
|
54
|
+
def inspect
|
|
55
|
+
"#<#{self.class} id:#{@id} name:\"#{@name}\">"
|
|
56
|
+
end
|
|
57
|
+
|
|
56
58
|
def get_tangent_node_by_virtual_index(virtual_index)
|
|
57
59
|
return nil if virtual_index.nil?
|
|
58
60
|
if virtual_index < 0
|
|
@@ -62,6 +64,22 @@ module Contrek
|
|
|
62
64
|
end
|
|
63
65
|
end
|
|
64
66
|
|
|
67
|
+
def nw_point
|
|
68
|
+
{x: min_x, y: y}
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def ne_point
|
|
72
|
+
{x: max_x, y: y}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def se_point
|
|
76
|
+
{x: max_x, y: y + 1}
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def sw_point
|
|
80
|
+
{x: min_x, y: y + 1}
|
|
81
|
+
end
|
|
82
|
+
|
|
65
83
|
def my_next(last, versus, mode)
|
|
66
84
|
last_node_index = if last.y < y
|
|
67
85
|
last.abs_x_index + @up_indexer
|
|
@@ -99,19 +117,19 @@ module Contrek
|
|
|
99
117
|
node_up = @cluster.vert_nodes[y + T_UP][-(tg_index + 1)]
|
|
100
118
|
if enter_mode == :a
|
|
101
119
|
enter_to.track |= TURNER[tracking][OMAX - 1]
|
|
102
|
-
point = node_up.
|
|
120
|
+
point = node_up.se_point
|
|
103
121
|
else
|
|
104
122
|
enter_to.track |= TURNER[tracking][OMIN - 1]
|
|
105
|
-
point = node_up.
|
|
123
|
+
point = node_up.sw_point
|
|
106
124
|
end
|
|
107
125
|
else
|
|
108
126
|
node_down = @cluster.vert_nodes[y + T_DOWN][tg_index]
|
|
109
127
|
if enter_mode == :a
|
|
110
128
|
enter_to.track |= TURNER[tracking][OMIN - 1]
|
|
111
|
-
point = node_down.
|
|
129
|
+
point = node_down.nw_point
|
|
112
130
|
else
|
|
113
131
|
enter_to.track |= TURNER[tracking][OMAX - 1]
|
|
114
|
-
point = node_down.
|
|
132
|
+
point = node_down.ne_point
|
|
115
133
|
end
|
|
116
134
|
end
|
|
117
135
|
point
|