geo_pattern 1.2.1 → 1.3.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.
@@ -0,0 +1,76 @@
1
+ module GeoPattern
2
+ class MosaicSquaresPattern < BasePattern
3
+ def render_to_svg
4
+ triangle_size = map(hex_val(0, 1), 0, 15, 15, 50)
5
+
6
+ svg.set_width(triangle_size * 8)
7
+ svg.set_height(triangle_size * 8)
8
+
9
+ i = 0
10
+ for y in 0..3
11
+ for x in 0..3
12
+ if x.even?
13
+ if y.even?
14
+ draw_outer_mosaic_tile(x*triangle_size*2, y*triangle_size*2, triangle_size, hex_val(i, 1))
15
+ else
16
+ draw_inner_mosaic_tile(x*triangle_size*2, y*triangle_size*2, triangle_size, [hex_val(i, 1), hex_val(i+1, 1)])
17
+ end
18
+ else
19
+ if y.even?
20
+ draw_inner_mosaic_tile(x*triangle_size*2, y*triangle_size*2, triangle_size, [hex_val(i, 1), hex_val(i+1, 1)])
21
+ else
22
+ draw_outer_mosaic_tile(x*triangle_size*2, y*triangle_size*2, triangle_size, hex_val(i, 1))
23
+ end
24
+ end
25
+ i += 1
26
+ end
27
+ end
28
+ end
29
+
30
+ def draw_inner_mosaic_tile(x, y, triangle_size, vals)
31
+ triangle = build_right_triangle_shape(triangle_size)
32
+ opacity = opacity(vals[0])
33
+ fill = fill_color(vals[0])
34
+ styles = {
35
+ "stroke" => STROKE_COLOR,
36
+ "stroke-opacity" => STROKE_OPACITY,
37
+ "fill-opacity" => opacity,
38
+ "fill" => fill
39
+ }
40
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{x+triangle_size}, #{y}) scale(-1, 1)"}))
41
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{x+triangle_size}, #{y+triangle_size*2}) scale(1, -1)"}))
42
+
43
+ opacity = opacity(vals[1])
44
+ fill = fill_color(vals[1])
45
+ styles = {
46
+ "stroke" => STROKE_COLOR,
47
+ "stroke-opacity" => STROKE_OPACITY,
48
+ "fill-opacity" => opacity,
49
+ "fill" => fill
50
+ }
51
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{x+triangle_size}, #{y+triangle_size*2}) scale(-1, -1)"}))
52
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{x+triangle_size}, #{y}) scale(1, 1)"}))
53
+ end
54
+
55
+ def draw_outer_mosaic_tile(x, y, triangle_size, val)
56
+ opacity = opacity(val)
57
+ fill = fill_color(val)
58
+ triangle = build_right_triangle_shape(triangle_size)
59
+ styles = {
60
+ "stroke" => STROKE_COLOR,
61
+ "stroke-opacity" => STROKE_OPACITY,
62
+ "fill-opacity" => opacity,
63
+ "fill" => fill
64
+ }
65
+
66
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{x}, #{y+triangle_size}) scale(1, -1)"}))
67
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{x+triangle_size*2}, #{y+triangle_size}) scale(-1, -1)"}))
68
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{x}, #{y+triangle_size}) scale(1, 1)"}))
69
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{x+triangle_size*2}, #{y+triangle_size}) scale(-1, 1)"}))
70
+ end
71
+
72
+ def build_right_triangle_shape(side_length)
73
+ "0, 0, #{side_length}, #{side_length}, 0, #{side_length}, 0, 0"
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,51 @@
1
+ module GeoPattern
2
+ class NestedSquaresPattern < BasePattern
3
+ def render_to_svg
4
+ block_size = map(hex_val(0, 1), 0, 15, 4, 12)
5
+ square_size = block_size * 7
6
+
7
+ svg.set_width((square_size + block_size)*6 + block_size*6)
8
+ svg.set_height((square_size + block_size)*6 + block_size*6)
9
+
10
+ i = 0
11
+ for y in 0..5
12
+ for x in 0..5
13
+ val = hex_val(i, 1)
14
+ opacity = opacity(val)
15
+ fill = fill_color(val)
16
+
17
+ styles = {
18
+ "fill" => "none",
19
+ "stroke" => fill,
20
+ "style" => {
21
+ "opacity" => opacity,
22
+ "stroke-width" => "#{block_size}px"
23
+ }
24
+ }
25
+
26
+ svg.rect(x*square_size + x*block_size*2 + block_size/2,
27
+ y*square_size + y*block_size*2 + block_size/2,
28
+ square_size, square_size, styles)
29
+
30
+ val = hex_val(39-i, 1)
31
+ opacity = opacity(val)
32
+ fill = fill_color(val)
33
+
34
+ styles = {
35
+ "fill" => "none",
36
+ "stroke" => fill,
37
+ "style" => {
38
+ "opacity" => opacity,
39
+ "stroke-width" => "#{block_size}px"
40
+ }
41
+ }
42
+
43
+ svg.rect(x*square_size + x*block_size*2 + block_size/2 + block_size*2,
44
+ y*square_size + y*block_size*2 + block_size/2 + block_size*2,
45
+ block_size * 3, block_size * 3, styles)
46
+ i += 1
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,35 @@
1
+ module GeoPattern
2
+ class OctagonPattern < BasePattern
3
+ def render_to_svg
4
+ square_size = map(hex_val(0, 1), 0, 15, 10, 60)
5
+ tile = build_octogon_shape(square_size)
6
+
7
+ svg.set_width(square_size * 6)
8
+ svg.set_height(square_size * 6)
9
+
10
+ i = 0
11
+ for y in 0..5
12
+ for x in 0..5
13
+ val = hex_val(i, 1)
14
+ opacity = opacity(val)
15
+ fill = fill_color(val)
16
+
17
+ svg.polyline(tile, {
18
+ "fill" => fill,
19
+ "fill-opacity" => opacity,
20
+ "stroke" => STROKE_COLOR,
21
+ "stroke-opacity" => STROKE_OPACITY,
22
+ "transform" => "translate(#{x*square_size}, #{y*square_size})"
23
+ })
24
+ i += 1
25
+ end
26
+ end
27
+ end
28
+
29
+ def build_octogon_shape(square_size)
30
+ s = square_size
31
+ c = s * 0.33
32
+ "#{c},0,#{s-c},0,#{s},#{c},#{s},#{s-c},#{s-c},#{s},#{c},#{s},0,#{s-c},0,#{c},#{c},0"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,46 @@
1
+ module GeoPattern
2
+ class OverlappingCirclesPattern < BasePattern
3
+ def render_to_svg
4
+ scale = hex_val(0, 1)
5
+ diameter = map(scale, 0, 15, 25, 200)
6
+ radius = diameter/2;
7
+
8
+ svg.set_width(radius * 6)
9
+ svg.set_height(radius * 6)
10
+
11
+ i = 0
12
+ for y in 0..5
13
+ for x in 0..5
14
+ val = hex_val(i, 1)
15
+ opacity = opacity(val)
16
+ fill = fill_color(val)
17
+
18
+ styles = {
19
+ "fill" => fill,
20
+ "style" => {
21
+ "opacity" => opacity
22
+ }
23
+ }
24
+
25
+ svg.circle(x*radius, y*radius, radius, styles)
26
+
27
+ # Add an extra one at top-right, for tiling.
28
+ if (x == 0)
29
+ svg.circle(6*radius, y*radius, radius, styles)
30
+ end
31
+
32
+ # Add an extra row at the end that matches the first row, for tiling.
33
+ if (y == 0)
34
+ svg.circle(x*radius, 6*radius, radius, styles)
35
+ end
36
+
37
+ # Add an extra one at bottom-right, for tiling.
38
+ if (x == 0 and y == 0)
39
+ svg.circle(6*radius, 6*radius, radius, styles)
40
+ end
41
+ i += 1
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,46 @@
1
+ module GeoPattern
2
+ class OverlappingRingsPattern < BasePattern
3
+ def render_to_svg
4
+ scale = hex_val(0, 1)
5
+ ring_size = map(scale, 0, 15, 10, 60)
6
+ stroke_width = ring_size / 4
7
+
8
+ svg.set_width(ring_size * 6)
9
+ svg.set_height(ring_size * 6)
10
+
11
+ i = 0
12
+ for y in 0..5
13
+ for x in 0..5
14
+ val = hex_val(i, 1)
15
+ opacity = opacity(val)
16
+ fill = fill_color(val)
17
+
18
+ styles = {
19
+ "fill" => "none",
20
+ "stroke" => fill,
21
+ "style" => {
22
+ "opacity" => opacity,
23
+ "stroke-width" => "#{stroke_width}px"
24
+ }
25
+ }
26
+
27
+ svg.circle(x*ring_size, y*ring_size, ring_size - stroke_width/2, styles)
28
+
29
+ # Add an extra one at top-right, for tiling.
30
+ if (x == 0)
31
+ svg.circle(6*ring_size, y*ring_size, ring_size - stroke_width/2, styles)
32
+ end
33
+
34
+ if (y == 0)
35
+ svg.circle(x*ring_size, 6*ring_size, ring_size - stroke_width/2, styles)
36
+ end
37
+
38
+ if (x == 0 and y == 0)
39
+ svg.circle(6*ring_size, 6*ring_size, ring_size - stroke_width/2, styles)
40
+ end
41
+ i += 1
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,19 @@
1
+ Dir[File.join(File.dirname(__FILE__), '**', '*.rb')].each { |file| require file }
2
+
3
+ module GeoPattern
4
+ module PatternHelpers
5
+ def self.hex_val(hash, index, length)
6
+ hash[index, length || 1].to_i(16)
7
+ end
8
+
9
+ # Ruby implementation of Processing's map function
10
+ # http://processing.org/reference/map_.html
11
+ def self.map(value, v_min, v_max, d_min, d_max) # v for value, d for desired
12
+ v_value = value.to_f # so it returns float
13
+
14
+ v_range = v_max - v_min
15
+ d_range = d_max - d_min
16
+ (v_value - v_min) * d_range / v_range + d_min
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,49 @@
1
+ module GeoPattern
2
+ class PlaidPattern < BasePattern
3
+ def render_to_svg
4
+ height = 0
5
+ width = 0
6
+
7
+ # horizontal stripes
8
+ i = 0
9
+ 18.times do
10
+ space = hex_val(i, 1)
11
+ height += space + 5
12
+
13
+ val = hex_val(i+1, 1)
14
+ opacity = opacity(val)
15
+ fill = fill_color(val)
16
+ stripe_height = val + 5
17
+
18
+ svg.rect(0, height, "100%", stripe_height, {
19
+ "opacity" => opacity,
20
+ "fill" => fill
21
+ })
22
+ height += stripe_height
23
+ i += 2
24
+ end
25
+
26
+ # vertical stripes
27
+ i = 0
28
+ 18.times do
29
+ space = hex_val(i, 1)
30
+ width += space + 5
31
+
32
+ val = hex_val(i+1, 1)
33
+ opacity = opacity(val)
34
+ fill = fill_color(val)
35
+ stripe_width = val + 5
36
+
37
+ svg.rect(width, 0, stripe_width, "100%", {
38
+ "opacity" => opacity,
39
+ "fill" => fill
40
+ })
41
+ width += stripe_width
42
+ i += 2
43
+ end
44
+
45
+ svg.set_width(width)
46
+ svg.set_height(height)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,53 @@
1
+ module GeoPattern
2
+ class PlusSignPattern < BasePattern
3
+ def render_to_svg
4
+ square_size = map(hex_val(0, 1), 0, 15, 10, 25)
5
+ plus_size = square_size * 3
6
+ plus_shape = build_plus_shape(square_size)
7
+
8
+ svg.set_width(square_size * 12)
9
+ svg.set_height(square_size * 12)
10
+
11
+ i = 0
12
+ for y in 0..5
13
+ for x in 0..5
14
+ val = hex_val(i, 1)
15
+ opacity = opacity(val)
16
+ fill = fill_color(val)
17
+ dx = (y % 2 == 0) ? 0 : 1
18
+
19
+ styles = {
20
+ "fill" => fill,
21
+ "stroke" => STROKE_COLOR,
22
+ "stroke-opacity" => STROKE_OPACITY,
23
+ "style" => {
24
+ "fill-opacity" => opacity
25
+ }
26
+ }
27
+
28
+ svg.group(plus_shape, styles.merge({
29
+ "transform" => "translate(#{x*plus_size - x*square_size + dx*square_size - square_size},#{y*plus_size - y*square_size - plus_size/2})"}))
30
+
31
+ # Add an extra column on the right for tiling.
32
+ if (x == 0)
33
+ svg.group(plus_shape, styles.merge({
34
+ "transform" => "translate(#{4*plus_size - x*square_size + dx*square_size - square_size},#{y*plus_size - y*square_size - plus_size/2})"}))
35
+ end
36
+
37
+ # Add an extra row on the bottom that matches the first row, for tiling.
38
+ if (y == 0)
39
+ svg.group(plus_shape, styles.merge({
40
+ "transform" => "translate(#{x*plus_size - x*square_size + dx*square_size - square_size},#{4*plus_size - y*square_size - plus_size/2})"}))
41
+ end
42
+
43
+ # Add an extra one at top-right and bottom-right, for tiling.
44
+ if (x == 0 && y == 0)
45
+ svg.group(plus_shape, styles.merge({
46
+ "transform" => "translate(#{4*plus_size - x*square_size + dx*square_size - square_size},#{4*plus_size - y*square_size - plus_size/2})"}))
47
+ end
48
+ i += 1
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,36 @@
1
+ module GeoPattern
2
+ class SineWavePattern < BasePattern
3
+ def render_to_svg
4
+ period = map(hex_val(0, 1), 0, 15, 100, 400).floor
5
+ amplitude = map(hex_val(1, 1), 0, 15, 30, 100).floor
6
+ wave_width = map(hex_val(2, 1), 0, 15, 3, 30).floor
7
+
8
+ svg.set_width(period)
9
+ svg.set_height(wave_width * 36)
10
+
11
+ for i in 0..35
12
+ val = hex_val(i, 1)
13
+ opacity = opacity(val)
14
+ fill = fill_color(val)
15
+ x_offset = period / 4 * 0.7
16
+
17
+ styles = {
18
+ "fill" => "none",
19
+ "stroke" => fill,
20
+ "style" => {
21
+ "opacity" => opacity,
22
+ "stroke-width" => "#{wave_width}px"
23
+ }
24
+ }
25
+
26
+ str = "M0 "+amplitude.to_s+
27
+ " C "+x_offset.to_s+" 0, "+(period/2 - x_offset).to_s+" 0, "+(period/2).to_s+" "+amplitude.to_s+
28
+ " S "+(period-x_offset).to_s+" "+(amplitude*2).to_s+", "+period.to_s+" "+amplitude.to_s+
29
+ " S "+(period*1.5-x_offset).to_s+" 0, "+(period*1.5).to_s+", "+amplitude.to_s;
30
+
31
+ svg.path(str, styles.merge({"transform" => "translate(-#{period/4}, #{wave_width*i-amplitude*1.5})"}))
32
+ svg.path(str, styles.merge({"transform" => "translate(-#{period/4}, #{wave_width*i-amplitude*1.5 + wave_width*36})"}))
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ module GeoPattern
2
+ class SquarePattern < BasePattern
3
+ def render_to_svg
4
+ square_size = map(hex_val(0, 1), 0, 15, 10, 60)
5
+
6
+ svg.set_width(square_size * 6)
7
+ svg.set_height(square_size * 6)
8
+
9
+ i = 0
10
+ for y in 0..5
11
+ for x in 0..5
12
+ val = hex_val(i, 1)
13
+ opacity = opacity(val)
14
+ fill = fill_color(val)
15
+
16
+ svg.rect(x*square_size, y*square_size, square_size, square_size, {
17
+ "fill" => fill,
18
+ "fill-opacity" => opacity,
19
+ "stroke" => STROKE_COLOR,
20
+ "stroke-opacity" => STROKE_OPACITY
21
+ })
22
+ i += 1
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end