Skip to content

Instantly share code, notes, and snippets.

@janpaul123
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save janpaul123/b2e6e0d2faef0bf99a22 to your computer and use it in GitHub Desktop.
Save janpaul123/b2e6e0d2faef0bf99a22 to your computer and use it in GitHub Desktop.
Mini Factwheels
# Made by @markijbema, based on @joelkuiper's SVG Factwheel
require 'rvg/rvg'
include Magick
include Math
class SvgWheelBuilder
def initialize(
percentages_max_colors=['#98d100', '#36A9E1', '#E94E1B'],
percentages_colors=['#dbeab3','#c5eaf8','#f8caba'], # green blue red
disabled_color = '#dadada'
)
#sanity check, if the color is in the wrong format imagemagick crashes in mysterious ways
[percentages_max_colors, percentages_colors, [disabled_color]].each do |colors|
colors.each do |color|
unless color =~ /^#[a-fA-F0-9]{6}$/
raise "Color should be in #xxxxxx format"
end
end
end
@disabled_color = disabled_color
@percentages_colors = percentages_colors
@percentages_max_colors = percentages_max_colors
end
def wheel(percentages)
RVG::Group.new do |canvas|
had = 0;
percentages.each_with_index do |percentage, index|
if percentage == percentages.max
stroke = @percentages_max_colors[index]
else
# stroke = @percentages_colors[index]
stroke = @disabled_color
end
canvas.path(arc_path(percentage,had,6)).styles(:fill => 'none', :stroke => stroke, :stroke_width => 4)
had += percentage
end
end
end
def string_for_float(f)
("%0.5f"%f).sub(/^-(0.0+)$/, '\1')
end
def arc_path(percentage, percentage_offset, radius)
large_angle = percentage > 50
start_angle = percentage_offset * 2*Math::PI / 100
end_angle = (percentage_offset + percentage) * 2*Math::PI / 100
start_x = radius * Math.cos(start_angle)
start_y = - radius * Math.sin(start_angle)
end_x = radius * Math.cos(end_angle)
end_y = - radius * Math.sin(end_angle)
path_string(start_x,start_y, end_x, end_y, large_angle, radius)
end
def path_string(start_x, start_y, end_x, end_y, large_angle, radius)
start_x = string_for_float(start_x)
start_y = string_for_float(start_y)
end_x = string_for_float(end_x)
end_y = string_for_float(end_y)
return [['M',start_x,start_y],
["A", radius, radius, 0, large_angle ? 1 : 0, 0, end_x, end_y]].flatten.join(' ')
end
end
class PercentageFormatter
def initialize(round_to, minimum)
@round_to = round_to
@minimum = minimum
end
DOUBT_INDEX = 1
def floor_percentages(percentages)
percentages.map {|x| ((x.to_f / @round_to )).floor.to_i * @round_to }
end
def cap_percentages(percentages)
round_to = @round_to
minimum = @minimum
after_total, large_ones = 0.0, 0.0
percentages.each do |percentage|
after_total += [percentage, minimum].max
if percentage > (100 - minimum)/2
large_ones += percentage
end
end
too_much = after_total - 100
percentages = percentages.map do |percentage|
if percentage < minimum
percentage = minimum
elsif percentage > (100-minimum)/2
percentage = percentage - percentage/large_ones*too_much
end
percentage.round
end
end
def process_percentages(percentages)
percentages = cap_percentages(percentages)
percentages = floor_percentages(percentages)
percentages[DOUBT_INDEX] += 100 - percentages.reduce(0,:+)
percentages
end
end
[
[100, 0, 0],
[0, 100, 0],
[0, 0, 100],
[10000, 8, 13],
[2, 1, 0],
[7839, 8009, 3041],
[182, 119, 1205],
[4, 2, 8],
[10, 3, 0],
[6, 4, 2],
[11, 2, 0],
[9, 3, 0],
[7, 0, 0],
[0, 2, 0],
[7, 2, 0],
[11, 4, 8],
].each do |values|
total = values.inject{|sum,x| sum + x }
percentages_wrong_order = values.map{|i| 100*i/total}
# we denote them in above in green,red,blue format, but the SvgWheelBuilder expects green,blue,red
percentages = [percentages_wrong_order[0], percentages_wrong_order[2], percentages_wrong_order[1]]
after_percentages = PercentageFormatter.new(5,15).process_percentages(percentages)
rvg = RVG.new(20,20).viewbox(0,0,20,20) do |canvas|
canvas.use(SvgWheelBuilder.new().wheel(after_percentages)).translate(10,10)
end
local_path = "#{values.join('-')}.png"
rvg.draw.write(local_path)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment