Class: Qrio::FinderPatternSlice
- Inherits:
-
Region
- Object
- Region
- Qrio::FinderPatternSlice
show all
- Defined in:
- lib/qrio/finder_pattern_slice.rb
Overview
QR codes have a finder pattern in three corners. any horizontal or vertical slice through the center square will be a band of: black, white, black, white, black, with widths matching ratio: 1, 1, 3, 1, 1. According to spec, the tolerance should be +/- 0.5.
Constant Summary
collapse
- ONE =
0.5..1.5
- THREE =
not to spec, but required for some “in-the-wild” QR
2.1..3.9
- ENDPOINT_TOLERANCE =
origin/terminus delta between adjacent slices
0.05
- OFFSET_TOLERANCE =
how many non-matching slices can be skipped?
0.25
- LENGTH_TOLERANCE =
allowed length delta bewteen 2 intersecting slices
0.35
- WIDTH_TOLERANCE =
allowed width delta bewteen 2 intersecting slices
0.15
Instance Attribute Summary collapse
Attributes inherited from Region
#orientation, #x1, #x2, #y1, #y2
Class Method Summary
collapse
Instance Method Summary
collapse
Methods inherited from Region
#==, #bottom, #bottom_right, #center, #eql?, #hash, #height, #horizontal?, #left, #orientation_matches?, #right, #rotate, #to_coordinates, #to_point_size, #top, #top_left, #translate, #union, #vertical?, #width
Constructor Details
Returns a new instance of FinderPatternSlice.
19
20
21
22
|
# File 'lib/qrio/finder_pattern_slice.rb', line 19
def initialize(*args)
@neighbors = []
super
end
|
Instance Attribute Details
#neighbors ⇒ Object
Returns the value of attribute neighbors.
16
17
18
|
# File 'lib/qrio/finder_pattern_slice.rb', line 16
def neighbors
@neighbors
end
|
#offset ⇒ Object
Returns the value of attribute offset.
17
18
19
|
# File 'lib/qrio/finder_pattern_slice.rb', line 17
def offset
@offset
end
|
#origin ⇒ Object
Returns the value of attribute origin.
17
18
19
|
# File 'lib/qrio/finder_pattern_slice.rb', line 17
def origin
@origin
end
|
#terminus ⇒ Object
Returns the value of attribute terminus.
17
18
19
|
# File 'lib/qrio/finder_pattern_slice.rb', line 17
def terminus
@terminus
end
|
Class Method Details
.build_matching(offset, origin, widths, direction) ⇒ Object
given a width buffer extracted from a given coordinate, test for ratio matching. if it matches, return a match object of the appropriate orientation
49
50
51
52
53
54
55
56
|
# File 'lib/qrio/finder_pattern_slice.rb', line 49
def build_matching(offset, origin, widths, direction)
return nil unless matches_ratio?(widths)
match_class = direction == :horizontal ? HorizontalMatch : VerticalMatch
terminus = origin + widths.inject(0){|s,w| s + w } - 1
match_class.build(offset, origin, terminus)
end
|
.matches_ratio?(widths) ⇒ Boolean
58
59
60
61
62
63
64
65
66
|
# File 'lib/qrio/finder_pattern_slice.rb', line 58
def matches_ratio?(widths)
norm = normalized_ratio(widths)
ONE.include?(norm[0]) &&
ONE.include?(norm[1]) &&
THREE.include?(norm[2]) &&
ONE.include?(norm[3]) &&
ONE.include?(norm[4])
end
|
.normalized_ratio(widths) ⇒ Object
68
69
70
71
|
# File 'lib/qrio/finder_pattern_slice.rb', line 68
def normalized_ratio(widths)
scale = (widths[0] + widths[1] + widths[3] + widths[4]) / 4.0
widths.map{|w| w / scale }
end
|
Instance Method Details
#<=>(other) ⇒ Object
74
75
76
77
78
|
# File 'lib/qrio/finder_pattern_slice.rb', line 74
def <=>(other)
return -1 if offset < other.offset
return 1 if offset > other.offset
origin <=> other.origin
end
|
#adjacent?(other) ⇒ Boolean
88
89
90
|
# File 'lib/qrio/finder_pattern_slice.rb', line 88
def adjacent?(other)
endpoints_match?(other) && offset_matches?(other)
end
|
#aspect_ratio ⇒ Object
32
33
34
|
# File 'lib/qrio/finder_pattern_slice.rb', line 32
def aspect_ratio
breadth / length.to_f
end
|
#breadth_diff(other) ⇒ Object
128
129
130
|
# File 'lib/qrio/finder_pattern_slice.rb', line 128
def breadth_diff(other)
(breadth - other.breadth).abs / breadth.to_f
end
|
#breadth_matches?(other) ⇒ Boolean
132
133
134
|
# File 'lib/qrio/finder_pattern_slice.rb', line 132
def breadth_matches?(other)
breadth_diff(other) <= WIDTH_TOLERANCE
end
|
#class_name_prefix ⇒ Object
28
29
30
|
# File 'lib/qrio/finder_pattern_slice.rb', line 28
def class_name_prefix
self.class.to_s.gsub(/^.*::/, '')[0,1]
end
|
#endpoints_match?(other) ⇒ Boolean
92
93
94
|
# File 'lib/qrio/finder_pattern_slice.rb', line 92
def endpoints_match?(other)
origin_matches?(other) && terminus_matches?(other)
end
|
#intersects?(other) ⇒ Boolean
80
81
82
83
84
85
86
|
# File 'lib/qrio/finder_pattern_slice.rb', line 80
def intersects?(other)
! orientation_matches?(other) &&
(other.origin..other.terminus).include?(offset) &&
(origin..terminus).include?(other.offset) &&
length_matches?(other) &&
breadth_matches?(other)
end
|
#length_diff(other) ⇒ Object
120
121
122
|
# File 'lib/qrio/finder_pattern_slice.rb', line 120
def length_diff(other)
(length - other.length).abs / length.to_f
end
|
#length_matches?(other) ⇒ Boolean
124
125
126
|
# File 'lib/qrio/finder_pattern_slice.rb', line 124
def length_matches?(other)
length_diff(other) <= LENGTH_TOLERANCE
end
|
#matches_aspect_ratio? ⇒ Boolean
based on the 1, 1, 3, 1, 1 width ratio, a finder pattern has total width of 7. an ideal grouped slice would then have aspect ratio of 3/7, since slice breadth would be 3 (just the center square) and length would be 7 (entire slice)
40
41
42
|
# File 'lib/qrio/finder_pattern_slice.rb', line 40
def matches_aspect_ratio?
(0.25..0.59).include? aspect_ratio
end
|
#normalized_offset_diff(other) ⇒ Object
112
113
114
|
# File 'lib/qrio/finder_pattern_slice.rb', line 112
def normalized_offset_diff(other)
offset_diff(other) / length.to_f
end
|
#offset_matches?(other) ⇒ Boolean
116
117
118
|
# File 'lib/qrio/finder_pattern_slice.rb', line 116
def offset_matches?(other)
normalized_offset_diff(other) <= OFFSET_TOLERANCE
end
|
#origin_diff(other) ⇒ Object
96
97
98
|
# File 'lib/qrio/finder_pattern_slice.rb', line 96
def origin_diff(other)
(origin - other.origin).abs / length.to_f
end
|
#origin_matches?(other) ⇒ Boolean
100
101
102
|
# File 'lib/qrio/finder_pattern_slice.rb', line 100
def origin_matches?(other)
origin_diff(other) <= ENDPOINT_TOLERANCE
end
|
#terminus_diff(other) ⇒ Object
104
105
106
|
# File 'lib/qrio/finder_pattern_slice.rb', line 104
def terminus_diff(other)
(terminus - other.terminus).abs / length.to_f
end
|
#terminus_matches?(other) ⇒ Boolean
108
109
110
|
# File 'lib/qrio/finder_pattern_slice.rb', line 108
def terminus_matches?(other)
terminus_diff(other) <= ENDPOINT_TOLERANCE
end
|
#to_s ⇒ Object
24
25
26
|
# File 'lib/qrio/finder_pattern_slice.rb', line 24
def to_s
"#{ class_name_prefix }[#{ to_coordinates.join(',') }]"
end
|