Class: Tiler

Inherits:
Object
  • Object
show all
Defined in:
lib/tiler.rb

Constant Summary collapse

@@translation_matrix =

The matrix that we multiply against the position of every face on tick

Matrix[[0, 0, 0, -1]

Instance Method Summary collapse

Constructor Details

#initialize(image_width, image_height, scale, hue, sat_major, sat_minor, projection_lambda) ⇒ Tiler

Returns a new instance of Tiler.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/tiler.rb', line 88

def initialize image_width, image_height, scale, hue, sat_major, sat_minor, projection_lambda
  
  # We colour based on face orientation index, 
  # 0 and 1 being white
  # 2 and 4 based on hue
  # 3 and 5 based on the compliment of hue

  @h1 = hue
  @h2 = (hue + 360/2) % 360
  
  @colors = [
    ChunkyPNG::Color.from_hsv(0, 0, 1),
    ChunkyPNG::Color.from_hsv(0, 0.0, 1),
    ChunkyPNG::Color.from_hsv(@h1, sat_major, 0.9),
    ChunkyPNG::Color.from_hsv(@h2, sat_major, 0.9),
    ChunkyPNG::Color.from_hsv(@h1, sat_minor, 0.6),
    ChunkyPNG::Color.from_hsv(@h2, sat_minor, 0.6)
  ]

  @image_width = image_width
  @image_height = image_height

  # (ox,oy) describes the centre of the image
  @ox = @image_width/2
  @oy = @image_height/2

  # Scale is the length in pixels of the unit distance when rendered
  @scale = scale

  # Construct the projection of 4 dimensional space onto the output image
  # (cononical_x[i],cononical_y[i]) describes the projection of e_i
  @canonical_x = []
  @canonical_y = []
  for i in 0..3 do
    c = projection_lambda ** i
    @canonical_x << c.real
    @canonical_y << c.imaginary
  end

  # Add an initial face to the list of faces
  @all_faces = [Face.new(Vector[0, 0, 0, 0], 2, 3)]

end

Instance Method Details

#tile(ticks, filename) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/tiler.rb', line 140

def tile ticks, filename
	
  # Iterate all faces ticks times
  for i in 1 .. ticks
    new_list = []
    @all_faces.each do |face|
      new_list << face
      ret = face.tick @@translation_matrix
      new_list << ret unless ret.nil?
    end
    @all_faces = new_list
  end

  # (global_xo, global_yo) is a translation of the entire rendered surface
  # we do this to centre on a region that is actually tiled
  
  @global_xo = 0
  @global_yo = 0

  # For now we focus on the average position of all faces
  @all_faces.each do |face|
    p = to_image_space(face.pos.to_a, @ox, @oy)
    @global_xo += (@ox - p[:x])/@all_faces.length
    @global_yo += (@oy - p[:y])/@all_faces.length
  end

  # Draw
  puts "Tiledenticon: Drawing image"
  
  # Create a new, blank image
  image = ChunkyPNG::Image.new @image_width, @image_height, @colors[5]

  draw_x = @global_xo + @ox
  draw_y = @global_yo + @oy

  @all_faces.each_with_index do |face, i|
    print "Tiledenticon: Face #{i}\r"

    # Generate the points to a from each face for rendering

    p1 = to_image_space  face.pos.to_a, draw_x, draw_y

    p2_m = face.pos.to_a
    p2_m[face.min_axis] += 1
    p2 = to_image_space p2_m, draw_x, draw_y

    p3_m = face.pos.to_a
    p3_m[face.max_axis] += 1
    p3 = to_image_space p3_m, draw_x, draw_y

    p4_m = face.pos.to_a
    p4_m[face.min_axis] += 1
    p4_m[face.max_axis] += 1
    p4 = to_image_space p4_m, draw_x, draw_y

    points = ChunkyPNG::Vector.new([p1, p2, p4, p3])

    # Pick colour based on colour scheme in @colors array and the direcion the
    # face is orientated
    color = @colors[min_max_to_i face.min_axis, face.max_axis]

    image.polygon(points, ChunkyPNG::Color::TRANSPARENT, color) 
  end

  puts "\nTiledenticon: Saving image to #{filename}"
  image.save(filename, :interlace => false)
end

#to_image_space(p, origin_x, origin_y) ⇒ Object

Convert a positional vector 4 to image space



133
134
135
136
137
138
# File 'lib/tiler.rb', line 133

def to_image_space p, origin_x, origin_y
  {x: (origin_x - @scale * (p[0] * @canonical_x[0] + p[1] * @canonical_x[1] + 
               p[2] * @canonical_x[2] + p[3] * @canonical_x[3])),
   y: (origin_y + @scale * (p[0] * @canonical_y[0] + p[1] * @canonical_y[1] + 
               p[2] * @canonical_y[2] + p[3] * @canonical_y[3]))};
end