-
Notifications
You must be signed in to change notification settings - Fork 90
Make it possible to reduce available patterns #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
76b5a9d
07fae49
8d6d1d0
051608b
8e3d65c
7856ecb
c190444
d49ed0f
3d71659
92d611e
fb0cca9
64b1793
fcc2101
38870d1
1b3a773
09db655
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module GeoPattern | ||
# user errors | ||
class UserError < StandardError; end | ||
|
||
# raised if an invalid pattern is requested | ||
class InvalidPatternError < UserError; end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
module GeoPattern | ||
class HashStore | ||
private | ||
|
||
attr_reader :hash | ||
|
||
public | ||
|
||
def initialize(hash) | ||
@hash = hash.each_with_object({}) { |(key, value), a| a[key.to_sym] = value } | ||
end | ||
|
||
def key?(obj) | ||
hash.key? obj.to_sym | ||
end | ||
|
||
def values | ||
hash.values | ||
end | ||
|
||
def value?(obj) | ||
hash.value? obj | ||
end | ||
|
||
def [](obj) | ||
hash[obj.to_sym] | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,46 @@ | ||
module GeoPattern | ||
module PatternHelpers | ||
def self.hex_val(hash, index, length) | ||
def hex_val(hash, index, length) | ||
hash[index, length || 1].to_i(16) | ||
end | ||
|
||
# Ruby implementation of Processing's map function | ||
# http://processing.org/reference/map_.html | ||
def self.map(value, v_min, v_max, d_min, d_max) # v for value, d for desired | ||
def map(value, v_min, v_max, d_min, d_max) # v for value, d for desired | ||
v_value = value.to_f # so it returns float | ||
|
||
v_range = v_max - v_min | ||
d_range = d_max - d_min | ||
(v_value - v_min) * d_range / v_range + d_min | ||
end | ||
|
||
def html_to_rgb(color) | ||
generate_rgb_string(Color::RGB.from_html(color)) | ||
end | ||
|
||
def html_to_rgb_for_string(hash, base_color) | ||
hue_offset = map(hex_val(hash, 14, 3), 0, 4095, 0, 359) | ||
sat_offset = hex_val(hash, 17, 1) | ||
base_color = Color::RGB.from_html(base_color).to_hsl | ||
base_color.hue = base_color.hue - hue_offset; | ||
|
||
if (sat_offset % 2 == 0) | ||
base_color.saturation = base_color.saturation + sat_offset | ||
else | ||
base_color.saturation = base_color.saturation - sat_offset | ||
end | ||
|
||
generate_rgb_string(base_color.to_rgb) | ||
end | ||
|
||
def generate_rgb_string(rgb) | ||
r = (rgb.r * 255).round | ||
g = (rgb.g * 255).round | ||
b = (rgb.b * 255).round | ||
|
||
format("rgb(%d, %d, %d)", r, g, b) | ||
end | ||
|
||
module_function :hex_val, :map, :html_to_rgb, :html_to_rgb_for_string, :generate_rgb_string | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
module GeoPattern | ||
class PatternSieve | ||
private | ||
|
||
attr_reader :pattern_store | ||
|
||
public | ||
|
||
def initialize(pattern_store = PatternStore.new) | ||
@pattern_store = pattern_store | ||
end | ||
|
||
def fetch(requested_patterns) | ||
requested_patterns = Array(requested_patterns).compact | ||
|
||
return pattern_store.all if requested_patterns.empty? | ||
|
||
requested_patterns.map { |p| pattern_store[p] }.compact | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
module GeoPattern | ||
class PatternStore | ||
private | ||
|
||
attr_reader :store | ||
|
||
public | ||
|
||
def initialize( | ||
store = HashStore.new( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is kind of a |
||
chevrons: ChevronPattern, | ||
concentric_circles: ConcentricCirclesPattern, | ||
diamonds: DiamondPattern, | ||
hexagons: HexagonPattern, | ||
mosaic_squares: MosaicSquaresPattern, | ||
nested_squares: NestedSquaresPattern, | ||
octagons: OctagonPattern, | ||
overlapping_circles: OverlappingCirclesPattern, | ||
overlapping_rings: OverlappingRingsPattern, | ||
plaid: PlaidPattern, | ||
plus_signs: PlusSignPattern, | ||
sine_waves: SineWavePattern, | ||
squares: SquarePattern, | ||
tessellation: TessellationPattern, | ||
triangles: TrianglePattern, | ||
xes: XesPattern | ||
) | ||
) | ||
|
||
@store = store | ||
end | ||
|
||
def [](pattern) | ||
if pattern.kind_of?(String) || pattern.kind_of?(Symbol) | ||
$stderr.puts 'String pattern references are deprecated as of 1.3.0' if pattern.kind_of?(String) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added the deprecation warnings for string + class. I can revert this change @jasonlong. It's just a single commit. |
||
|
||
return store[pattern] | ||
end | ||
|
||
if store.value? pattern | ||
$stderr.puts 'Class pattern references are deprecated as of 1.3.0' | ||
|
||
return pattern | ||
end | ||
|
||
nil | ||
end | ||
|
||
def all | ||
store.values | ||
end | ||
|
||
def known?(pattern) | ||
return store.key?(pattern) if pattern.kind_of?(String) || pattern.kind_of?(Symbol) | ||
return store.value?(pattern) if pattern.kind_of? Class | ||
|
||
false | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
module GeoPattern | ||
class PatternValidator | ||
private | ||
|
||
attr_reader :pattern_store | ||
|
||
public | ||
|
||
def initialize(pattern_store = PatternStore.new) | ||
@pattern_store = pattern_store | ||
end | ||
|
||
def validate(requested_patterns) | ||
message = "Error: At least one of the requested patterns \"#{requested_patterns.join(", ")}\" is invalid" | ||
|
||
fail InvalidPatternError, message unless valid?(requested_patterns) | ||
|
||
self | ||
end | ||
|
||
private | ||
|
||
def valid?(requested_patterns) | ||
requested_patterns.all? { |p| pattern_store.known? p } | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using this kind of pattern for exceptions is a question of style. If you do not like it, I can remove the "intermediate" error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have an opinion on this. @ttaylorr, do you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use this pattern all the time -- looks great.