tiledenticon 0.0.1 → 0.1.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 (5) hide show
  1. checksums.yaml +4 -4
  2. data/lib/face.rb +31 -3
  3. data/lib/tiledenticon.rb +19 -11
  4. data/lib/tiler.rb +63 -38
  5. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c856d1f52ab0369d34a8abd4a42a85d7272b7053
4
- data.tar.gz: f3e5d7a662f909d76bc0d1e11db31dfddba547f9
3
+ metadata.gz: 91badaf0443b9bb80e880a8a54881c93c2335fd2
4
+ data.tar.gz: 3af121955ad819c7a80d7d95e78ba921bcde29b0
5
5
  SHA512:
6
- metadata.gz: 65a6ee4426399a52b244a059d70a58e6cbf01dea68b4721cbbb77475d74b6f92d4de68c302bb96f585c00ed027bb1d0cb4bfed1ec96cdd016bfbfb11a140ec10
7
- data.tar.gz: 14b4b0cdaf46d353d8055eecfb9e111c5b6553ff4eefe6b1b836c388b24a468a6b215815f46cd6f9f33d8c48d0ff540fc37c199baf13acfae9297036c3bb584b
6
+ metadata.gz: 3db670823e703c28d7a8a66d90c64bea4c447bc62eea83f7aa0a32138481f67a3b237622ec077ab4db7453db0fe0b9273a53d81831c5332d8d0f453cced8ac79
7
+ data.tar.gz: f16c265b4dbab6475b9461aa53e6859cdd285fbe2ca53fecf859af2042177c8ef0fbef9934e5f9e2f23107f1868e7d22b7049b43af1115129b3c213e73bffd48
data/lib/face.rb CHANGED
@@ -1,10 +1,24 @@
1
+ # Warning, documentation written in mathsspeak
2
+ #
1
3
  class Face
2
- def initialize x, axis1, axis2
3
- @pos = x
4
+ # Represents a 2-dimensional tile with sides of unit length in 4-dimensional
5
+ # space
6
+ # V is a vector4 representing the position of the faces base vertex
7
+ # Axis1 and axis2 are the two canonical axis that the face is aligned with
8
+
9
+ def initialize v, axis1, axis2
10
+ @pos = v
4
11
  @a_min = min(axis1, axis2)
5
12
  @a_max = max(axis1, axis2)
6
13
  end
7
14
 
15
+ # One iteration of the system
16
+ # Position is multiplied by translation_matrix
17
+ # Faces are updated based on algorithm encoded here with switch statements
18
+ #
19
+ # There are some cases where the face splits in two, so we return either a new
20
+ # face or nil
21
+
8
22
  def tick translation_matrix
9
23
  ret = nil
10
24
  @pos = translation_matrix * @pos
@@ -45,11 +59,15 @@ class Face
45
59
  return ret
46
60
  end
47
61
 
62
+ # There are several cases in tick where we 'shunt' the position of the face by
63
+ # a constant translation
48
64
  private def shunt_pos
49
65
  a = @pos.to_a
50
- @pos = Vector[a[0] - $dirmultx, a[1], a[2], a[3] + $dirmultx]
66
+ @pos = Vector[a[0] - 1, a[1], a[2], a[3] + 1]
51
67
  end
52
68
 
69
+ # Getters
70
+
53
71
  def pos
54
72
  @pos
55
73
  end
@@ -62,3 +80,13 @@ class Face
62
80
  @a_max
63
81
  end
64
82
  end
83
+
84
+ # Return min of a series of values
85
+ def min(*values)
86
+ values.min
87
+ end
88
+
89
+ # Return max of a series of values
90
+ def max(*values)
91
+ values.max
92
+ end
data/lib/tiledenticon.rb CHANGED
@@ -1,32 +1,40 @@
1
1
  require 'tiler.rb'
2
2
 
3
3
  class Tiledenticon
4
+ # Wrapper for the classes defined in this library
5
+
4
6
  def initialize out_folder
5
7
  @out_folder = out_folder
6
8
  end
7
- def create input
9
+
10
+ def create str
11
+ # Create a new md5 hasher and feed in the input string
8
12
  md5 = Digest::MD5.new
9
- md5 << input
13
+ md5 << str
10
14
  hash = md5.hexdigest
15
+ hr = Hashrander.new hash
11
16
 
12
- fromMD5 "#{@out_folder}/#{input}.png", hash
17
+ fromHashrander "#{@out_folder}/#{str}.png", hr
13
18
  end
14
19
 
20
+ # Create a series of parameters from an Hashrander
15
21
  private
16
- def fromMD5 filename, hash
17
- r = Hashrander.new(hash)
18
- hue = r.get_rand 3, 360
19
- s1 = 0.5 + (r.get_rand 2, 0.5)
20
- s2 = 0.5 + (r.get_rand 2, 0.5 * s1)
22
+ def fromHashrander filename, hr
23
+ hue = hr.get_rand 3, 360
24
+ s1 = 0.5 + (hr.get_rand 2, 0.5)
25
+ s2 = 0.4 + (hr.get_rand 2, 0.6 * s1)
21
26
 
22
- p_x = 0.5 + (r.get_rand 2, 1.15)
23
- p_y = 0.5 + (r.get_rand 2, 1.15)
27
+ p_x = 0.5 + (hr.get_rand 2, 1.15)
28
+ p_y = 0.5 + (hr.get_rand 2, 1.15)
24
29
 
25
- TilerBuilder.new(filename).set_hue(hue).set_sat_major(s1).set_sat_minor(s2).set_projection_lambda(p_x, p_y).build
30
+ TilerBuilder.new(filename).set_hue(hue).set_sat_major(s1).set_sat_minor(s2).set_projection_lambda(p_x, p_y).set_ticks(16).build
26
31
  end
27
32
  end
28
33
 
29
34
  class Hashrander
35
+
36
+ # Generate random numbers of arbitrary size from a hash
37
+
30
38
  def initialize hash
31
39
  @hash_i = 0
32
40
  @hash = hash
data/lib/tiler.rb CHANGED
@@ -1,30 +1,22 @@
1
- # From here
2
- # http://www.mathematicians.org.uk/eoh/files/Harriss_ANGASRP.pdf
3
-
4
1
  require 'face'
5
2
 
6
3
  require 'chunky_png'
7
4
  require 'matrix'
8
5
  require 'digest'
9
6
 
10
- def min(*values)
11
- values.min
12
- end
13
-
14
- def max(*values)
15
- values.max
16
- end
7
+ # Warning, documentation written in mathsspeak
17
8
 
9
+ # Convert min axis, max axis tuple to an orientation index
10
+ # where axis is between 1 and 4
11
+ # and min_axis < max_axis
18
12
  def min_max_to_i min, max
19
13
  return max - 1 if min == 0
20
14
  return 1 + max if min == 1
21
15
  return 5
22
16
  end
23
- $dirmultx = 1
24
- $dirmulty = 1
25
-
26
17
 
27
18
  class TilerBuilder
19
+ # Builder class for Tiler
28
20
 
29
21
  def initialize filename
30
22
  @hue = 345
@@ -87,32 +79,44 @@ end
87
79
 
88
80
  class Tiler
89
81
 
82
+ # The matrix that we multiply against the position of every face on tick
90
83
  @@translation_matrix =
91
84
  Matrix[[0, 0, 0, -1],
92
- [1, 0, 0, 0],
93
- [0, 1, 0, 0],
94
- [0, 0, 1, 1]]
85
+ [1, 0, 0, 0],
86
+ [0, 1, 0, 0],
87
+ [0, 0, 1, 1]]
95
88
 
96
89
  def initialize image_width, image_height, scale, hue, sat_major, sat_minor, projection_lambda
90
+
91
+ # We colour based on face orientation index,
92
+ # 0 and 1 being white
93
+ # 2 and 4 based on hue
94
+ # 3 and 5 based on the compliment of hue
95
+
97
96
  @h1 = hue
98
97
  @h2 = (hue + 360/2) % 360
99
-
98
+
100
99
  @colors = [
101
100
  ChunkyPNG::Color.from_hsv(0, 0, 1),
102
101
  ChunkyPNG::Color.from_hsv(0, 0.0, 1),
103
- ChunkyPNG::Color.from_hsv(@h1, sat_major, 1),
104
- ChunkyPNG::Color.from_hsv(@h2, sat_major, 1),
102
+ ChunkyPNG::Color.from_hsv(@h1, sat_major, 0.9),
103
+ ChunkyPNG::Color.from_hsv(@h2, sat_major, 0.9),
105
104
  ChunkyPNG::Color.from_hsv(@h1, sat_minor, 0.6),
106
105
  ChunkyPNG::Color.from_hsv(@h2, sat_minor, 0.6)
107
106
  ]
108
107
 
109
-
110
108
  @image_width = image_width
111
109
  @image_height = image_height
110
+
111
+ # (ox,oy) describes the centre of the image
112
112
  @ox = @image_width/2
113
113
  @oy = @image_height/2
114
+
115
+ # Scale is the length in pixels of the unit distance when rendered
114
116
  @scale = scale
115
117
 
118
+ # Construct the projection of 4 dimensional space onto the output image
119
+ # (cononical_x[i],cononical_y[i]) describes the projection of e_i
116
120
  @canonical_x = []
117
121
  @canonical_y = []
118
122
  for i in 0..3 do
@@ -120,19 +124,23 @@ class Tiler
120
124
  @canonical_x << c.real
121
125
  @canonical_y << c.imaginary
122
126
  end
123
- @all_faces = [Face.new(Vector[0, 0, 0, 0], 2, 3)]
124
- end
125
127
 
128
+ # Add an initial face to the list of faces
129
+ @all_faces = [Face.new(Vector[0, 0, 0, 0], 2, 3)]
126
130
 
131
+ end
127
132
 
128
- def to_image_space p
129
- {x: (@ox + @global_xo -@scale * (p[0] * @canonical_x[0] + p[1] * @canonical_x[1] +
133
+ # Convert a positional vector 4 to image space
134
+ def to_image_space p, origin_x, origin_y
135
+ {x: (origin_x - @scale * (p[0] * @canonical_x[0] + p[1] * @canonical_x[1] +
130
136
  p[2] * @canonical_x[2] + p[3] * @canonical_x[3])),
131
- y: (@oy + @global_yo + @scale * (p[0] * @canonical_y[0] + p[1] * @canonical_y[1] +
137
+ y: (origin_y + @scale * (p[0] * @canonical_y[0] + p[1] * @canonical_y[1] +
132
138
  p[2] * @canonical_y[2] + p[3] * @canonical_y[3]))};
133
139
  end
134
140
 
135
141
  def tile ticks, filename
142
+
143
+ # Iterate all faces ticks times
136
144
  for i in 1 .. ticks
137
145
  new_list = []
138
146
  @all_faces.each do |face|
@@ -141,42 +149,59 @@ class Tiler
141
149
  new_list << ret unless ret.nil?
142
150
  end
143
151
  @all_faces = new_list
152
+ end
144
153
 
145
- @global_xo = 0
146
- @global_yo = 0
147
- p = to_image_space(@all_faces[0].pos.to_a)
148
- @global_xo = @ox - p[:x]
149
- @global_yo = @oy - p[:y]
150
-
154
+ # (global_xo, global_yo) is a translation of the entire rendered surface
155
+ # we do this to centre on a region that is actually tiled
156
+
157
+ @global_xo = 0
158
+ @global_yo = 0
159
+
160
+ # For now we focus on the average position of all faces
161
+ @all_faces.each do |face|
162
+ p = to_image_space(face.pos.to_a, @ox, @oy)
163
+ @global_xo += (@ox - p[:x])/@all_faces.length
164
+ @global_yo += (@oy - p[:y])/@all_faces.length
151
165
  end
152
166
 
153
167
  # Draw
154
- image = ChunkyPNG::Image.new(@image_width, @image_height, ChunkyPNG::Color::TRANSPARENT)
155
-
156
168
  puts "Tiledenticon: Drawing image"
169
+
170
+ # Create a new, blank image
171
+ image = ChunkyPNG::Image.new @image_width, @image_height, @colors[5]
172
+
173
+ draw_x = @global_xo + @ox
174
+ draw_y = @global_yo + @oy
175
+
157
176
  @all_faces.each_with_index do |face, i|
158
177
  print "Tiledenticon: Face #{i}\r"
159
178
 
160
- p1 = to_image_space (face.pos.to_a)
179
+ # Generate the points to a from each face for rendering
180
+
181
+ p1 = to_image_space face.pos.to_a, draw_x, draw_y
161
182
 
162
183
  p2_m = face.pos.to_a
163
184
  p2_m[face.min_axis] += 1
164
- p2 = to_image_space(p2_m)
185
+ p2 = to_image_space p2_m, draw_x, draw_y
165
186
 
166
187
  p3_m = face.pos.to_a
167
188
  p3_m[face.max_axis] += 1
168
- p3 = to_image_space(p3_m)
189
+ p3 = to_image_space p3_m, draw_x, draw_y
169
190
 
170
191
  p4_m = face.pos.to_a
171
192
  p4_m[face.min_axis] += 1
172
193
  p4_m[face.max_axis] += 1
173
- p4 = to_image_space(p4_m)
174
-
194
+ p4 = to_image_space p4_m, draw_x, draw_y
175
195
 
176
196
  points = ChunkyPNG::Vector.new([p1, p2, p4, p3])
197
+
198
+ # Pick colour based on colour scheme in @colors array and the direcion the
199
+ # face is orientated
177
200
  color = @colors[min_max_to_i face.min_axis, face.max_axis]
201
+
178
202
  image.polygon(points, ChunkyPNG::Color::TRANSPARENT, color)
179
203
  end
204
+
180
205
  puts "\nTiledenticon: Saving image to #{filename}"
181
206
  image.save(filename, :interlace => false)
182
207
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tiledenticon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Slocombe