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