geo_pattern 1.3.2 → 1.5.0

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.
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