geo_pattern 1.3.2 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +30 -0
  3. data/.gitignore +1 -0
  4. data/.simplecov +26 -0
  5. data/Gemfile +17 -17
  6. data/README.md +154 -29
  7. data/Rakefile +72 -13
  8. data/fixtures/generated_patterns/chevrons.svg +1 -0
  9. data/fixtures/generated_patterns/concentric_circles.svg +1 -0
  10. data/fixtures/generated_patterns/diamonds.svg +1 -0
  11. data/fixtures/generated_patterns/diamonds_with_base_color.svg +1 -0
  12. data/fixtures/generated_patterns/diamonds_with_color.svg +1 -0
  13. data/fixtures/generated_patterns/hexagons.svg +1 -0
  14. data/fixtures/generated_patterns/mosaic_squares.svg +1 -0
  15. data/fixtures/generated_patterns/nested_squares.svg +1 -0
  16. data/fixtures/generated_patterns/octagons.svg +1 -0
  17. data/fixtures/generated_patterns/overlapping_circles.svg +1 -0
  18. data/fixtures/generated_patterns/overlapping_rings.svg +1 -0
  19. data/fixtures/generated_patterns/plaid.svg +1 -0
  20. data/fixtures/generated_patterns/plus_signs.svg +1 -0
  21. data/fixtures/generated_patterns/sine_waves.svg +1 -0
  22. data/fixtures/generated_patterns/squares.svg +1 -0
  23. data/fixtures/generated_patterns/tessellation.svg +1 -0
  24. data/fixtures/generated_patterns/triangles.svg +1 -0
  25. data/fixtures/generated_patterns/xes.svg +1 -0
  26. data/geo_pattern.gemspec +19 -17
  27. data/lib/geo_pattern/background.rb +27 -0
  28. data/lib/geo_pattern/background_generators/solid_generator.rb +54 -0
  29. data/lib/geo_pattern/color.rb +27 -0
  30. data/lib/geo_pattern/color_generators/base_color_generator.rb +57 -0
  31. data/lib/geo_pattern/color_generators/simple_generator.rb +29 -0
  32. data/lib/geo_pattern/color_preset.rb +32 -0
  33. data/lib/geo_pattern/errors.rb +9 -0
  34. data/lib/geo_pattern/geo_pattern_task.rb +61 -0
  35. data/lib/geo_pattern/helpers.rb +50 -1
  36. data/lib/geo_pattern/pattern.rb +86 -0
  37. data/lib/geo_pattern/pattern_generator.rb +34 -81
  38. data/lib/geo_pattern/pattern_helpers.rb +34 -2
  39. data/lib/geo_pattern/pattern_preset.rb +25 -0
  40. data/lib/geo_pattern/pattern_sieve.rb +38 -0
  41. data/lib/geo_pattern/pattern_store.rb +65 -0
  42. data/lib/geo_pattern/pattern_validator.rb +29 -0
  43. data/lib/geo_pattern/rake_task.rb +112 -0
  44. data/lib/geo_pattern/roles/comparable_metadata.rb +37 -0
  45. data/lib/geo_pattern/roles/named_generator.rb +15 -0
  46. data/lib/geo_pattern/seed.rb +23 -0
  47. data/lib/geo_pattern/structure.rb +27 -0
  48. data/lib/geo_pattern/structure_generators/base_generator.rb +88 -0
  49. data/lib/geo_pattern/structure_generators/chevrons_generator.rb +57 -0
  50. data/lib/geo_pattern/structure_generators/concentric_circles_generator.rb +58 -0
  51. data/lib/geo_pattern/structure_generators/diamonds_generator.rb +72 -0
  52. data/lib/geo_pattern/structure_generators/hexagons_generator.rb +69 -0
  53. data/lib/geo_pattern/structure_generators/mosaic_squares_generator.rb +85 -0
  54. data/lib/geo_pattern/structure_generators/nested_squares_generator.rb +62 -0
  55. data/lib/geo_pattern/structure_generators/octagons_generator.rb +45 -0
  56. data/lib/geo_pattern/structure_generators/overlapping_circles_generator.rb +57 -0
  57. data/lib/geo_pattern/structure_generators/overlapping_rings_generator.rb +57 -0
  58. data/lib/geo_pattern/structure_generators/plaid_generator.rb +55 -0
  59. data/lib/geo_pattern/structure_generators/plus_signs_generator.rb +68 -0
  60. data/lib/geo_pattern/structure_generators/sine_waves_generator.rb +45 -0
  61. data/lib/geo_pattern/structure_generators/squares_generator.rb +37 -0
  62. data/lib/geo_pattern/structure_generators/tessellation_generator.rb +105 -0
  63. data/lib/geo_pattern/structure_generators/triangles_generator.rb +64 -0
  64. data/lib/geo_pattern/structure_generators/xes_generator.rb +74 -0
  65. data/lib/geo_pattern/svg_image.rb +103 -0
  66. data/lib/geo_pattern/version.rb +3 -1
  67. data/lib/geo_pattern.rb +54 -30
  68. data/script/bootstrap +30 -0
  69. data/script/console +9 -0
  70. data/script/test +21 -0
  71. data/spec/background_generators/solid_generator_spec.rb +52 -0
  72. data/spec/background_spec.rb +27 -0
  73. data/spec/color_generators/base_color_generator_spec.rb +33 -0
  74. data/spec/color_generators/simple_generator_spec.rb +14 -0
  75. data/spec/color_preset_spec.rb +55 -0
  76. data/spec/color_spec.rb +17 -0
  77. data/spec/geo_pattern_spec.rb +98 -26
  78. data/spec/helpers_spec.rb +67 -0
  79. data/spec/pattern_preset_spec.rb +43 -0
  80. data/spec/pattern_sieve_spec.rb +68 -0
  81. data/spec/pattern_spec.rb +74 -0
  82. data/spec/pattern_store_spec.rb +49 -0
  83. data/spec/pattern_validator_spec.rb +30 -0
  84. data/spec/seed_spec.rb +16 -0
  85. data/spec/spec_helper.rb +9 -13
  86. data/spec/structure_generators/chevrons_generator_spec.rb +7 -0
  87. data/spec/structure_generators/concentric_circles_generator_spec.rb +7 -0
  88. data/spec/structure_generators/diamonds_generator_spec.rb +7 -0
  89. data/spec/structure_generators/hexagons_generator_spec.rb +7 -0
  90. data/spec/structure_generators/mosaic_squares_generator_spec.rb +7 -0
  91. data/spec/structure_generators/nested_squares_generator_spec.rb +7 -0
  92. data/spec/structure_generators/octagons_generator_spec.rb +7 -0
  93. data/spec/structure_generators/overlapping_circles_generator_spec.rb +7 -0
  94. data/spec/structure_generators/overlapping_rings_generator_spec.rb +7 -0
  95. data/spec/structure_generators/plaid_generator_spec.rb +7 -0
  96. data/spec/structure_generators/plus_signs_generator_spec.rb +7 -0
  97. data/spec/structure_generators/sine_waves_generator_spec.rb +7 -0
  98. data/spec/structure_generators/squares_generator_spec.rb +7 -0
  99. data/spec/structure_generators/tessellation_generator_spec.rb +7 -0
  100. data/spec/structure_generators/triangles_generator_spec.rb +7 -0
  101. data/spec/structure_generators/xes_generator_spec.rb +7 -0
  102. data/spec/structure_spec.rb +40 -0
  103. data/spec/support/aruba.rb +6 -6
  104. data/spec/support/helpers/fixtures.rb +14 -0
  105. data/spec/support/kernel.rb +46 -0
  106. data/spec/support/matchers/image.rb +19 -0
  107. data/spec/support/matchers/name.rb +17 -0
  108. data/spec/support/rspec.rb +4 -2
  109. data/spec/support/shared_examples/generator.rb +48 -0
  110. data/spec/support/shared_examples/pattern.rb +33 -0
  111. data/spec/support/shared_examples/pattern_name.rb +9 -0
  112. data/spec/support/shared_examples/structure.rb +50 -0
  113. data/spec/support/string.rb +3 -2
  114. data/spec/svg_spec.rb +8 -6
  115. metadata +105 -37
  116. data/.rubocop.yml +0 -13
  117. data/lib/geo_pattern/pattern/base_pattern.rb +0 -47
  118. data/lib/geo_pattern/pattern/chevron_pattern.rb +0 -45
  119. data/lib/geo_pattern/pattern/concentric_circles_pattern.rb +0 -47
  120. data/lib/geo_pattern/pattern/diamond_pattern.rb +0 -56
  121. data/lib/geo_pattern/pattern/hexagon_pattern.rb +0 -57
  122. data/lib/geo_pattern/pattern/mosaic_squares_pattern.rb +0 -76
  123. data/lib/geo_pattern/pattern/nested_squares_pattern.rb +0 -51
  124. data/lib/geo_pattern/pattern/octagon_pattern.rb +0 -35
  125. data/lib/geo_pattern/pattern/overlapping_circles_pattern.rb +0 -46
  126. data/lib/geo_pattern/pattern/overlapping_rings_pattern.rb +0 -46
  127. data/lib/geo_pattern/pattern/plaid_pattern.rb +0 -49
  128. data/lib/geo_pattern/pattern/plus_sign_pattern.rb +0 -53
  129. data/lib/geo_pattern/pattern/sine_wave_pattern.rb +0 -36
  130. data/lib/geo_pattern/pattern/square_pattern.rb +0 -27
  131. data/lib/geo_pattern/pattern/tessellation_pattern.rb +0 -93
  132. data/lib/geo_pattern/pattern/triangle_pattern.rb +0 -51
  133. data/lib/geo_pattern/pattern/xes_pattern.rb +0 -58
  134. data/lib/geo_pattern/svg.rb +0 -77
  135. data/spec/support/helpers.rb +0 -34
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GeoPattern
4
+ module StructureGenerators
5
+ class HexagonsGenerator < BaseGenerator
6
+ private
7
+
8
+ attr_reader :scale, :side_length, :hex_height, :hex_width, :hex
9
+
10
+ def after_initialize
11
+ @scale = hex_val(0, 1)
12
+ @side_length = map(scale, 0, 15, 8, 60)
13
+ @hex_height = side_length * Math.sqrt(3)
14
+ @hex_width = side_length * 2
15
+ @hex = build_hexagon_shape(side_length)
16
+
17
+ self.width = hex_width * 3 + side_length * 3
18
+ self.height = hex_height * 6
19
+ end
20
+
21
+ def generate_structure
22
+ i = 0
23
+ 6.times do |y|
24
+ 6.times do |x|
25
+ val = hex_val(i, 1)
26
+ dy = (x % 2 == 0) ? y * hex_height : y * hex_height + hex_height / 2
27
+ opacity = opacity(val)
28
+ fill = fill_color(val)
29
+
30
+ styles = {
31
+ "fill" => fill,
32
+ "fill-opacity" => opacity,
33
+ "stroke" => stroke_color,
34
+ "stroke-opacity" => stroke_opacity
35
+ }
36
+
37
+ svg.polyline(hex, styles.merge("transform" => "translate(#{x * side_length * 1.5 - hex_width / 2}, #{dy - hex_height / 2})"))
38
+
39
+ # Add an extra one at top-right, for tiling.
40
+ if x == 0
41
+ svg.polyline(hex, styles.merge("transform" => "translate(#{6 * side_length * 1.5 - hex_width / 2}, #{dy - hex_height / 2})"))
42
+ end
43
+
44
+ # Add an extra row at the end that matches the first row, for tiling.
45
+ if y == 0
46
+ dy = (x % 2 == 0) ? 6 * hex_height : 6 * hex_height + hex_height / 2
47
+ svg.polyline(hex, styles.merge("transform" => "translate(#{x * side_length * 1.5 - hex_width / 2}, #{dy - hex_height / 2})"))
48
+ end
49
+
50
+ # Add an extra one at bottom-right, for tiling.
51
+ if x == 0 && y == 0
52
+ svg.polyline(hex, styles.merge("transform" => "translate(#{6 * side_length * 1.5 - hex_width / 2}, #{5 * hex_height + hex_height / 2})"))
53
+ end
54
+ i += 1
55
+ end
56
+ end
57
+
58
+ svg
59
+ end
60
+
61
+ def build_hexagon_shape(side_length)
62
+ c = side_length
63
+ a = c / 2
64
+ b = Math.sin(60 * Math::PI / 180) * c
65
+ "0,#{b},#{a},0,#{a + c},0,#{2 * c},#{b},#{a + c},#{2 * b},#{a},#{2 * b},0,#{b}"
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GeoPattern
4
+ module StructureGenerators
5
+ class MosaicSquaresGenerator < BaseGenerator
6
+ private
7
+
8
+ attr_reader :triangle_size
9
+
10
+ def after_initialize
11
+ @triangle_size = map(hex_val(0, 1), 0, 15, 15, 50)
12
+
13
+ self.height = self.width = triangle_size * 8
14
+ end
15
+
16
+ def generate_structure
17
+ i = 0
18
+ 4.times do |y|
19
+ 4.times do |x|
20
+ if x.even?
21
+ if y.even?
22
+ draw_outer_mosaic_tile(x * triangle_size * 2, y * triangle_size * 2, triangle_size, hex_val(i, 1))
23
+ else
24
+ draw_inner_mosaic_tile(x * triangle_size * 2, y * triangle_size * 2, triangle_size, [hex_val(i, 1), hex_val(i + 1, 1)])
25
+ end
26
+ elsif y.even?
27
+ draw_inner_mosaic_tile(x * triangle_size * 2, y * triangle_size * 2, triangle_size, [hex_val(i, 1), hex_val(i + 1, 1)])
28
+ else
29
+ draw_outer_mosaic_tile(x * triangle_size * 2, y * triangle_size * 2, triangle_size, hex_val(i, 1))
30
+ end
31
+ i += 1
32
+ end
33
+ end
34
+
35
+ svg
36
+ end
37
+
38
+ def draw_inner_mosaic_tile(x, y, triangle_size, vals)
39
+ triangle = build_right_triangle_shape(triangle_size)
40
+ opacity = opacity(vals[0])
41
+ fill = fill_color(vals[0])
42
+ styles = {
43
+ "stroke" => stroke_color,
44
+ "stroke-opacity" => stroke_opacity,
45
+ "fill-opacity" => opacity,
46
+ "fill" => fill
47
+ }
48
+ svg.polyline(triangle, styles.merge("transform" => "translate(#{x + triangle_size}, #{y}) scale(-1, 1)"))
49
+ svg.polyline(triangle, styles.merge("transform" => "translate(#{x + triangle_size}, #{y + triangle_size * 2}) scale(1, -1)"))
50
+
51
+ opacity = opacity(vals[1])
52
+ fill = fill_color(vals[1])
53
+ styles = {
54
+ "stroke" => stroke_color,
55
+ "stroke-opacity" => stroke_opacity,
56
+ "fill-opacity" => opacity,
57
+ "fill" => fill
58
+ }
59
+ svg.polyline(triangle, styles.merge("transform" => "translate(#{x + triangle_size}, #{y + triangle_size * 2}) scale(-1, -1)"))
60
+ svg.polyline(triangle, styles.merge("transform" => "translate(#{x + triangle_size}, #{y}) scale(1, 1)"))
61
+ end
62
+
63
+ def draw_outer_mosaic_tile(x, y, triangle_size, val)
64
+ opacity = opacity(val)
65
+ fill = fill_color(val)
66
+ triangle = build_right_triangle_shape(triangle_size)
67
+ styles = {
68
+ "stroke" => stroke_color,
69
+ "stroke-opacity" => stroke_opacity,
70
+ "fill-opacity" => opacity,
71
+ "fill" => fill
72
+ }
73
+
74
+ svg.polyline(triangle, styles.merge("transform" => "translate(#{x}, #{y + triangle_size}) scale(1, -1)"))
75
+ svg.polyline(triangle, styles.merge("transform" => "translate(#{x + triangle_size * 2}, #{y + triangle_size}) scale(-1, -1)"))
76
+ svg.polyline(triangle, styles.merge("transform" => "translate(#{x}, #{y + triangle_size}) scale(1, 1)"))
77
+ svg.polyline(triangle, styles.merge("transform" => "translate(#{x + triangle_size * 2}, #{y + triangle_size}) scale(-1, 1)"))
78
+ end
79
+
80
+ def build_right_triangle_shape(side_length)
81
+ "0, 0, #{side_length}, #{side_length}, 0, #{side_length}, 0, 0"
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GeoPattern
4
+ module StructureGenerators
5
+ class NestedSquaresGenerator < BaseGenerator
6
+ private
7
+
8
+ attr_reader :block_size, :square_size
9
+
10
+ def after_initialize
11
+ @block_size = map(hex_val(0, 1), 0, 15, 4, 12)
12
+ @square_size = block_size * 7
13
+
14
+ self.height = self.width = (square_size + block_size) * 6 + block_size * 6
15
+ end
16
+
17
+ def generate_structure
18
+ i = 0
19
+ 6.times do |y|
20
+ 6.times do |x|
21
+ val = hex_val(i, 1)
22
+ opacity = opacity(val)
23
+ fill = fill_color(val)
24
+
25
+ styles = {
26
+ "fill" => "none",
27
+ "stroke" => fill,
28
+ "style" => {
29
+ "opacity" => opacity,
30
+ "stroke-width" => "#{block_size}px"
31
+ }
32
+ }
33
+
34
+ svg.rect(x * square_size + x * block_size * 2 + block_size / 2,
35
+ y * square_size + y * block_size * 2 + block_size / 2,
36
+ square_size, square_size, styles)
37
+
38
+ val = hex_val(39 - i, 1)
39
+ opacity = opacity(val)
40
+ fill = fill_color(val)
41
+
42
+ styles = {
43
+ "fill" => "none",
44
+ "stroke" => fill,
45
+ "style" => {
46
+ "opacity" => opacity,
47
+ "stroke-width" => "#{block_size}px"
48
+ }
49
+ }
50
+
51
+ svg.rect(x * square_size + x * block_size * 2 + block_size / 2 + block_size * 2,
52
+ y * square_size + y * block_size * 2 + block_size / 2 + block_size * 2,
53
+ block_size * 3, block_size * 3, styles)
54
+ i += 1
55
+ end
56
+ end
57
+
58
+ svg
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GeoPattern
4
+ module StructureGenerators
5
+ class OctagonsGenerator < BaseGenerator
6
+ private
7
+
8
+ attr_reader :square_size, :tile
9
+
10
+ def after_initialize
11
+ @square_size = map(hex_val(0, 1), 0, 15, 10, 60)
12
+ @tile = build_octogon_shape(square_size)
13
+
14
+ self.height = self.width = square_size * 6
15
+ end
16
+
17
+ def generate_structure
18
+ i = 0
19
+ 6.times do |y|
20
+ 6.times do |x|
21
+ val = hex_val(i, 1)
22
+ opacity = opacity(val)
23
+ fill = fill_color(val)
24
+
25
+ svg.polyline(tile,
26
+ "fill" => fill,
27
+ "fill-opacity" => opacity,
28
+ "stroke" => stroke_color,
29
+ "stroke-opacity" => stroke_opacity,
30
+ "transform" => "translate(#{x * square_size}, #{y * square_size})")
31
+ i += 1
32
+ end
33
+ end
34
+
35
+ svg
36
+ end
37
+
38
+ def build_octogon_shape(square_size)
39
+ s = square_size
40
+ c = s * 0.33
41
+ "#{c},0,#{s - c},0,#{s},#{c},#{s},#{s - c},#{s - c},#{s},#{c},#{s},0,#{s - c},0,#{c},#{c},0"
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GeoPattern
4
+ module StructureGenerators
5
+ class OverlappingCirclesGenerator < BaseGenerator
6
+ private
7
+
8
+ attr_reader :scale, :diameter, :radius
9
+
10
+ def after_initialize
11
+ @scale = hex_val(0, 1)
12
+ @diameter = map(scale, 0, 15, 25, 200)
13
+ @radius = diameter / 2
14
+
15
+ self.height = self.width = radius * 6
16
+ end
17
+
18
+ def generate_structure
19
+ i = 0
20
+ 6.times do |y|
21
+ 6.times do |x|
22
+ val = hex_val(i, 1)
23
+ opacity = opacity(val)
24
+ fill = fill_color(val)
25
+
26
+ styles = {
27
+ "fill" => fill,
28
+ "style" => {
29
+ "opacity" => opacity
30
+ }
31
+ }
32
+
33
+ svg.circle(x * radius, y * radius, radius, styles)
34
+
35
+ # Add an extra one at top-right, for tiling.
36
+ if x == 0
37
+ svg.circle(6 * radius, y * radius, radius, styles)
38
+ end
39
+
40
+ # Add an extra row at the end that matches the first row, for tiling.
41
+ if y == 0
42
+ svg.circle(x * radius, 6 * radius, radius, styles)
43
+ end
44
+
45
+ # Add an extra one at bottom-right, for tiling.
46
+ if x == 0 && y == 0
47
+ svg.circle(6 * radius, 6 * radius, radius, styles)
48
+ end
49
+ i += 1
50
+ end
51
+ end
52
+
53
+ svg
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GeoPattern
4
+ module StructureGenerators
5
+ class OverlappingRingsGenerator < BaseGenerator
6
+ private
7
+
8
+ attr_reader :scale, :ring_size, :stroke_width
9
+
10
+ def after_initialize
11
+ @scale = hex_val(0, 1)
12
+ @ring_size = map(scale, 0, 15, 10, 60)
13
+ @stroke_width = ring_size / 4
14
+
15
+ self.height = self.width = ring_size * 6
16
+ end
17
+
18
+ def generate_structure
19
+ i = 0
20
+ 6.times do |y|
21
+ 6.times do |x|
22
+ val = hex_val(i, 1)
23
+ opacity = opacity(val)
24
+ fill = fill_color(val)
25
+
26
+ styles = {
27
+ "fill" => "none",
28
+ "stroke" => fill,
29
+ "style" => {
30
+ "opacity" => opacity,
31
+ "stroke-width" => "#{stroke_width}px"
32
+ }
33
+ }
34
+
35
+ svg.circle(x * ring_size, y * ring_size, ring_size - stroke_width / 2, styles)
36
+
37
+ # Add an extra one at top-right, for tiling.
38
+ if x == 0
39
+ svg.circle(6 * ring_size, y * ring_size, ring_size - stroke_width / 2, styles)
40
+ end
41
+
42
+ if y == 0
43
+ svg.circle(x * ring_size, 6 * ring_size, ring_size - stroke_width / 2, styles)
44
+ end
45
+
46
+ if x == 0 && y == 0
47
+ svg.circle(6 * ring_size, 6 * ring_size, ring_size - stroke_width / 2, styles)
48
+ end
49
+ i += 1
50
+ end
51
+ end
52
+
53
+ svg
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GeoPattern
4
+ module StructureGenerators
5
+ class PlaidGenerator < BaseGenerator
6
+ private
7
+
8
+ def generate_structure
9
+ local_height = 0
10
+ local_width = 0
11
+
12
+ # horizontal stripes
13
+ i = 0
14
+ 18.times do
15
+ space = hex_val(i, 1)
16
+ local_height += space + 5
17
+
18
+ val = hex_val(i + 1, 1)
19
+ opacity = opacity(val)
20
+ fill = fill_color(val)
21
+ stripe_height = val + 5
22
+
23
+ svg.rect(0, local_height, "100%", stripe_height,
24
+ "opacity" => opacity,
25
+ "fill" => fill)
26
+ local_height += stripe_height
27
+ i += 2
28
+ end
29
+
30
+ # vertical stripes
31
+ i = 0
32
+ 18.times do
33
+ space = hex_val(i, 1)
34
+ local_width += space + 5
35
+
36
+ val = hex_val(i + 1, 1)
37
+ opacity = opacity(val)
38
+ fill = fill_color(val)
39
+ stripe_width = val + 5
40
+
41
+ svg.rect(local_width, 0, stripe_width, "100%",
42
+ "opacity" => opacity,
43
+ "fill" => fill)
44
+ local_width += stripe_width
45
+ i += 2
46
+ end
47
+
48
+ self.height = local_height
49
+ self.width = local_width
50
+
51
+ svg
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GeoPattern
4
+ module StructureGenerators
5
+ class PlusSignsGenerator < BaseGenerator
6
+ private
7
+
8
+ attr_reader :square_size, :plus_size, :plus_shape
9
+
10
+ def after_initialize
11
+ @square_size = map(hex_val(0, 1), 0, 15, 10, 25)
12
+ @plus_size = square_size * 3
13
+ @plus_shape = build_plus_shape(square_size)
14
+
15
+ self.height = self.width = square_size * 12
16
+ end
17
+
18
+ def generate_structure
19
+ i = 0
20
+ 6.times do |y|
21
+ 6.times do |x|
22
+ val = hex_val(i, 1)
23
+ opacity = opacity(val)
24
+ fill = fill_color(val)
25
+ dx = (y % 2 == 0) ? 0 : 1
26
+
27
+ styles = {
28
+ "fill" => fill,
29
+ "stroke" => stroke_color,
30
+ "stroke-opacity" => stroke_opacity,
31
+ "style" => {
32
+ "fill-opacity" => opacity
33
+ }
34
+ }
35
+
36
+ svg.group(plus_shape, styles.merge(
37
+ "transform" => "translate(#{x * plus_size - x * square_size + dx * square_size - square_size},#{y * plus_size - y * square_size - plus_size / 2})"
38
+ ))
39
+
40
+ # Add an extra column on the right for tiling.
41
+ if x == 0
42
+ svg.group(plus_shape, styles.merge(
43
+ "transform" => "translate(#{4 * plus_size - x * square_size + dx * square_size - square_size},#{y * plus_size - y * square_size - plus_size / 2})"
44
+ ))
45
+ end
46
+
47
+ # Add an extra row on the bottom that matches the first row, for tiling.
48
+ if y == 0
49
+ svg.group(plus_shape, styles.merge(
50
+ "transform" => "translate(#{x * plus_size - x * square_size + dx * square_size - square_size},#{4 * plus_size - y * square_size - plus_size / 2})"
51
+ ))
52
+ end
53
+
54
+ # Add an extra one at top-right and bottom-right, for tiling.
55
+ if x == 0 && y == 0
56
+ svg.group(plus_shape, styles.merge(
57
+ "transform" => "translate(#{4 * plus_size - x * square_size + dx * square_size - square_size},#{4 * plus_size - y * square_size - plus_size / 2})"
58
+ ))
59
+ end
60
+ i += 1
61
+ end
62
+ end
63
+
64
+ svg
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GeoPattern
4
+ module StructureGenerators
5
+ class SineWavesGenerator < BaseGenerator
6
+ private
7
+
8
+ attr_reader :period, :amplitude, :wave_width
9
+
10
+ def after_initialize
11
+ @period = map(hex_val(0, 1), 0, 15, 100, 400).floor
12
+ @amplitude = map(hex_val(1, 1), 0, 15, 30, 100).floor
13
+ @wave_width = map(hex_val(2, 1), 0, 15, 3, 30).floor
14
+
15
+ self.height = wave_width * 36
16
+ self.width = period
17
+ end
18
+
19
+ def generate_structure
20
+ 36.times do |i|
21
+ val = hex_val(i, 1)
22
+ opacity = opacity(val)
23
+ fill = fill_color(val)
24
+ x_offset = period / 4 * 0.7
25
+
26
+ styles = {
27
+ "fill" => "none",
28
+ "stroke" => fill,
29
+ "style" => {
30
+ "opacity" => opacity,
31
+ "stroke-width" => "#{wave_width}px"
32
+ }
33
+ }
34
+
35
+ str = "M0 #{amplitude} C #{x_offset} 0, #{period / 2 - x_offset} 0, #{period / 2} #{amplitude} S #{period - x_offset} #{amplitude * 2}, #{period} #{amplitude} S #{period * 1.5 - x_offset} 0, #{period * 1.5}, #{amplitude}"
36
+
37
+ svg.path(str, styles.merge("transform" => "translate(-#{period / 4}, #{wave_width * i - amplitude * 1.5})"))
38
+ svg.path(str, styles.merge("transform" => "translate(-#{period / 4}, #{wave_width * i - amplitude * 1.5 + wave_width * 36})"))
39
+ end
40
+
41
+ svg
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GeoPattern
4
+ module StructureGenerators
5
+ class SquaresGenerator < BaseGenerator
6
+ private
7
+
8
+ attr_reader :square_size
9
+
10
+ def after_initialize
11
+ @square_size = map(hex_val(0, 1), 0, 15, 10, 60)
12
+
13
+ self.height = self.width = square_size * 6
14
+ end
15
+
16
+ def generate_structure
17
+ i = 0
18
+ 6.times do |y|
19
+ 6.times do |x|
20
+ val = hex_val(i, 1)
21
+ opacity = opacity(val)
22
+ fill = fill_color(val)
23
+
24
+ svg.rect(x * square_size, y * square_size, square_size, square_size,
25
+ "fill" => fill,
26
+ "fill-opacity" => opacity,
27
+ "stroke" => stroke_color,
28
+ "stroke-opacity" => stroke_opacity)
29
+ i += 1
30
+ end
31
+ end
32
+
33
+ svg
34
+ end
35
+ end
36
+ end
37
+ end