Class: ChemScanner::Interpreter::Arrow

Inherits:
Object
  • Object
show all
Defined in:
lib/chem_scanner/interpreter/element/arrow.rb

Overview

Base Arrow, independent from reader

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(geometry) ⇒ Arrow

Polyline path: tail -> middle1 -> middle2 -> … -> head



14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 14

def initialize(geometry)
  @geometry = geometry
  @id = geometry.id
  @tail = Geometry::Point.new(geometry.tail[:x], geometry.tail[:y])
  @head = Geometry::Point.new(geometry.head[:x], geometry.head[:y])

  @middle_points = []
  @cross = geometry.cross?
  @line_type = geometry.line_type
  @cross_lines = []
  @height = 0
  @text_arr = []
  @reagents_polygons = []
end

Instance Attribute Details

#crossObject

Returns the value of attribute cross.



9
10
11
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 9

def cross
  @cross
end

#cross_linesObject

Returns the value of attribute cross_lines.



9
10
11
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 9

def cross_lines
  @cross_lines
end

#descriptionsObject

Returns the value of attribute descriptions.



9
10
11
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 9

def descriptions
  @descriptions
end

#headObject

Returns the value of attribute head.



9
10
11
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 9

def head
  @head
end

#heightObject

Returns the value of attribute height.



9
10
11
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 9

def height
  @height
end

#idObject

Returns the value of attribute id.



9
10
11
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 9

def id
  @id
end

#line_typeObject

Returns the value of attribute line_type.



9
10
11
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 9

def line_type
  @line_type
end

#middle_pointsObject

Returns the value of attribute middle_points.



9
10
11
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 9

def middle_points
  @middle_points
end

#reagents_polygonsObject

Returns the value of attribute reagents_polygons.



9
10
11
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 9

def reagents_polygons
  @reagents_polygons
end

#tailObject

Returns the value of attribute tail.



9
10
11
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 9

def tail
  @tail
end

#text_arrObject

Returns the value of attribute text_arr.



9
10
11
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 9

def text_arr
  @text_arr
end

Instance Method Details

#add_cross_segment(other) ⇒ Object



83
84
85
86
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 83

def add_cross_segment(other)
  @cross_lines.push(other)
  @cross = true
end

#all_intersects_with_segment?(segment) ⇒ Boolean

Returns:

  • (Boolean)


213
214
215
216
217
218
219
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 213

def all_intersects_with_segment?(segment)
  @reagents_polygons.each do |rpoly|
    return false unless segment.intersects_with_polygon?(rpoly)
  end

  true
end

#build_polygons(height) ⇒ Object

Polyline path: tail -> middle1 -> middle2 -> … -> head



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 103

def build_polygons(height)
  @height = height
  @reagents_polygons = []

  segments.each do |segment|
    p1, p2 = segment.head_perpen_points_dist(height)
    p3, p4 = segment.tail_perpen_points_dist(height)

    polygon = Geometry::Polygon.new([p1, p2, p4, p3])
    @reagents_polygons.push(polygon)
  end
end

#build_polygons_on_polygons(polygons) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 116

def build_polygons_on_polygons(polygons)
  list_height = []
  @reagents_polygons = []

  segments.each do |segment|
    p1 = segment.point1
    p2 = segment.point2
    hperpen = segment.to_line.perpen_line_via_point(p1)
    tperpen = segment.to_line.perpen_line_via_point(p2)

    list_points = []

    polygons.each do |poly|
      next unless segment.polygon_in_range(poly)

      poly_points = poly.vertices.each_with_object([]) do |v, arr|
        arr.push(hperpen.point_projection(v))
        arr.push(tperpen.point_projection(v))
      end
      list_points.concat(poly_points).concat([p1, p2])
    end

    if list_points.empty?
      build_polygons(0.2)
      next
    end

    xmax = list_points.map(&:x).max + 0.5
    xmin = list_points.map(&:x).min - 0.5
    ymin = list_points.map(&:y).min - 0.5
    ymax = list_points.map(&:y).max + 0.5

    poly_points = [
      Geometry::Point.new(xmin, ymin),
      Geometry::Point.new(xmin, ymax),
      Geometry::Point.new(xmax, ymax),
      Geometry::Point.new(xmax, ymin),
    ]
    list_height.push((ymax - ymin).abs)

    @reagents_polygons.push(Geometry::Polygon.new(poly_points))
  end

  @height = list_height.max || 0.1
end

#change_head(new_head) ⇒ Object



88
89
90
91
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 88

def change_head(new_head)
  @middle_points.push(@head)
  @head = Geometry::Point.new(new_head[:x], new_head[:y])
end

#change_tail(new_tail) ⇒ Object



93
94
95
96
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 93

def change_tail(new_tail)
  @middle_points.unshift(@tail)
  @tail = Geometry::Point.new(new_tail.x, new_tail.y)
end

#cloneObject



260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 260

def clone
  cloned = self.class.new(@geometry)
  cloned.id = get_tempid

  cloned.tail = @tail.clone
  cloned.head = @head.clone
  cloned.middle_points = Marshal.load(Marshal.dump(@middle_points))

  cloned.descriptions = @descriptions
  cloned.cross = @cross
  cloned.cross_lines = Marshal.load(Marshal.dump(@cross_lines))
  cloned.reagents_polygons = @reagents_polygons.clone
  cloned.height = @height
  cloned.line_type = @line_type

  cloned
end

#contains_point?(point) ⇒ Boolean

Returns:

  • (Boolean)


176
177
178
179
180
181
182
183
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 176

def contains_point?(point)
  segments.each do |segment|
    ppoint = segment.to_line.point_projection(point)
    return ppoint if segment.contains_point?(ppoint)
  end

  nil
end

#dist_to_head(point) ⇒ Object



197
198
199
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 197

def dist_to_head(point)
  Geometry::Segment.new(point, @head).length
end

#dist_to_tail(point) ⇒ Object



201
202
203
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 201

def dist_to_tail(point)
  Geometry::Segment.new(point, @tail).length
end

#get_tempidObject



278
279
280
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 278

def get_tempid
  @geometry.get_tempid
end

#head_perpen_pointsObject



50
51
52
53
54
55
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 50

def head_perpen_points
  return nil if @head.nil? || @height.zero?

  tail = @middle_points.count.zero? ? @tail : @middle_points.last
  Geometry::Segment.new(tail, @head).tail_perpen_points_dist(@height)
end

#head_perpen_segmentObject



57
58
59
60
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 57

def head_perpen_segment
  p1, p2 = head_perpen_points
  Geometry::Segment.new(p1, p2)
end

#head_segmentObject



45
46
47
48
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 45

def head_segment
  point = @middle_points.count.zero? ? @tail : @middle_points.last
  Geometry::Segment.new(point, @head)
end

#inspectObject



282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 282

def inspect
  (
    "#<Arrow: id=#{id}, " +
      "reagents_polygon: #{reagents_polygons}," +
      "tail: #{tail}, " +
      "head: #{head}, " +
      "middle_points: #{middle_points}, " +
      "cross: #{cross}, " +
      "height: #{height}, " +
      "line_type: #{line_type}, " +
      "cross_lines: #{cross_lines}, " +
      "text_arr: #{text_arr} >"
  )
end

#min_distance_to_polygon(polygon) ⇒ Object



185
186
187
188
189
190
191
192
193
194
195
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 185

def min_distance_to_polygon(polygon)
  dist_arr = []
  bbox = polygon.bounding_box

  segments.each do |segment|
    dist = segment.distance_to_boundingbox(bbox)
    dist_arr.push(dist)
  end

  dist_arr.min
end

#parallel_to?(other) ⇒ Boolean

Returns:

  • (Boolean)


221
222
223
224
225
226
227
228
229
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 221

def parallel_to?(other)
  segments.each do |seg|
    other.segments.each do |oseg|
      return false unless seg.parallel_to?(oseg)
    end
  end

  true
end

#point_in_middle(target_point) ⇒ Object



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 242

def point_in_middle(target_point)
  in_middle = false

  points.each_with_index do |point, idx|
    next if idx.zero?

    segment = Geometry::Segment.new(point, points[idx - 1])
    ppoint = segment.to_line.point_projection(target_point)

    from_head = if idx == 1 then true
                elsif idx == (points.size - 1) then false
                end
    in_middle |= segment.point_in_range(ppoint, 4.0 / 5.0, from_head)
  end

  in_middle
end

#pointsObject



29
30
31
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 29

def points
  [@tail] + @middle_points + [@head]
end

#poly_in_middle?(poly) ⇒ Boolean

Returns:

  • (Boolean)


231
232
233
234
235
236
237
238
239
240
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 231

def poly_in_middle?(poly)
  poly_points = poly.bounding_box.points.push(poly.center)

  in_middle = false
  poly_points.each do |point|
    in_middle |= point_in_middle(point)
  end

  in_middle
end

#polygon_around?(poly) ⇒ Boolean

Returns:

  • (Boolean)


205
206
207
208
209
210
211
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 205

def polygon_around?(poly)
  @reagents_polygons.each do |rpoly|
    return true if poly.around_polygon?(rpoly)
  end

  false
end

#product_side?(point) ⇒ Boolean

Returns:

  • (Boolean)


162
163
164
165
166
167
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 162

def product_side?(point)
  line = head_perpen_segment.to_line
  side = line.point_side(@head) * line.point_side(point)

  side.positive?
end

#reactant_side?(point) ⇒ Boolean

Returns:

  • (Boolean)


169
170
171
172
173
174
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 169

def reactant_side?(point)
  line = tail_perpen_segment.to_line
  side = line.point_side(@tail) * line.point_side(point)

  side.positive?
end

#segmentsObject



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 33

def segments
  arr = []
  points.each_with_index do |point, idx|
    next if idx == points.count - 1

    segment = Geometry::Segment.new(point, points[idx + 1])
    arr.push(segment)
  end

  arr
end

#tail_head_segmentObject



79
80
81
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 79

def tail_head_segment
  Geometry::Segment.new(@tail, @head)
end

#tail_perpen_pointsObject



67
68
69
70
71
72
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 67

def tail_perpen_points
  return nil if @tail.nil? || @height.zero?

  head = @middle_points.count.zero? ? @head : @middle_points.first
  Geometry::Segment.new(@tail, head).head_perpen_points_dist(@height)
end

#tail_perpen_segmentObject



74
75
76
77
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 74

def tail_perpen_segment
  p1, p2 = tail_perpen_points
  Geometry::Segment.new(p1, p2)
end

#tail_segmentObject



62
63
64
65
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 62

def tail_segment
  point = @middle_points.count.zero? ? @head : @middle_points.first
  Geometry::Segment.new(point, @tail)
end

#update_tail(new_tail) ⇒ Object



98
99
100
# File 'lib/chem_scanner/interpreter/element/arrow.rb', line 98

def update_tail(new_tail)
  @tail = Geometry::Point.new(new_tail.x, new_tail.y)
end