Skip to content

Instantly share code, notes, and snippets.

@takehiko
Created April 25, 2021 00:48
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 takehiko/f14256f2956c2b9adecab29c4691a166 to your computer and use it in GitHub Desktop.
Save takehiko/f14256f2956c2b9adecab29c4691a166 to your computer and use it in GitHub Desktop.
A dot generator for math education
#!/usr/bin/env ruby
# hexdot-generator.rb : A dot generator for math education
# by takehikom
# see also: https://takehikom.hateblo.jp/entry/2021/04/25/082407
class HexdotGenerator
def initialize(opt = {})
@filename = opt[:file] || "hexdot.svg"
setup
end
def setup
@row = 3
@col = 8
@radius = 8
@distance = @radius * 6
@margin = @radius * 4
@image_width = (@margin * 2 + @distance * (@col - 1)).to_i
@image_height = (@margin * 2 + @distance * Math.sqrt(3.0) * 0.5 * (@row - 1)).to_i
@io = nil
end
attr_reader :row, :col, :radius
attr_reader :distance, :margin
attr_reader :image_width, :image_height
attr_reader :io
def coord(x, y)
x_coord = @margin + @distance * x
x_coord += @distance * 0.5 if y.odd?
y_coord = @margin + @distance * Math.sqrt(3.0) * 0.5 * y
[x_coord, y_coord]
end
def start(&block_draw)
@io = open(@filename, "w")
@io.puts('<svg xmlns="http://www.w3.org/2000/svg" width="%dpx" height="%dpx">' % [@image_width, @image_height])
@io.puts('<rect x="0" y="0" width="%d" height="%d" fill="#f0fff0"/>' % [@image_width, @image_height])
if block_given?
block_draw.call(self)
end
@row.times do |y|
(y.even? ? @col : (@col - 1)).times do |x|
x_coord, y_coord = coord(x, y)
# $stderr.puts("DEBUG: x=#{x}, y=#{y}, x_coord=#{x_coord}, y_coord=#{y_coord}")
@io.puts('<circle cx="%f" cy="%f" r="%f" fill="black" stroke="none"/>' % [x_coord, y_coord, @radius])
end
end
@io.puts('</svg>')
@io.close
@io = nil
self
end
end
if __FILE__ == $0
HexdotGenerator.new(file: "hexdot0.svg").start
HexdotGenerator.new(file: "hexdot1.svg").start do |h_o|
h_o.row.times do |y1|
x1 = 0
# y1 = 0
x2 = h_o.col - 1 - (y1.odd? ? 1 : 0)
y2 = y1
x1_coord, y1_coord = h_o.send(:coord, x1, y1)
x2_coord, y2_coord = h_o.send(:coord, x2, y2)
stroke_color = ["red", "green", "blue"][y1 % 3]
stroke_width = h_o.radius * 0.33
h_o.io.puts('<line x1="%f" y1="%f" x2="%f" y2="%f" stroke="%s" stroke-width="%f"/>' % [x1_coord, y1_coord, x2_coord, y2_coord, stroke_color, stroke_width])
end
end
HexdotGenerator.new(file: "hexdot2.svg").start do |h_o|
# It will be wrong if h_o.row != 3
h_o.col.times do |x1|
y1 = 0
x2 = x1
y2 = h_o.row - 1
x1_coord, y1_coord = h_o.send(:coord, x1, y1)
x2_coord, y2_coord = h_o.send(:coord, x2, y2)
stroke_color = "blue"
stroke_width = h_o.radius * 0.33
h_o.io.puts('<line x1="%f" y1="%f" x2="%f" y2="%f" stroke="%s" stroke-width="%f"/>' % [x1_coord, y1_coord, x2_coord, y2_coord, stroke_color, stroke_width])
end
x1 = 0
y1 = 1
x2 = h_o.col - 2
y2 = y1
x1_coord, y1_coord = h_o.send(:coord, x1, y1)
x2_coord, y2_coord = h_o.send(:coord, x2, y2)
stroke_color = "green"
stroke_width = h_o.radius * 0.33
h_o.io.puts('<line x1="%f" y1="%f" x2="%f" y2="%f" stroke="%s" stroke-width="%f"/>' % [x1_coord, y1_coord, x2_coord, y2_coord, stroke_color, stroke_width])
end
HexdotGenerator.new(file: "hexdot3.svg").start do |h_o|
1.upto(h_o.col - 1) do |x1|
coord_a = []
h_o.row.times do |y1|
x = x1 - (y1.odd? ? 1 : 0)
y = y1
x_coord, y_coord = h_o.send(:coord, x, y)
coord_a << x_coord << y_coord
end
stroke_color = "blue"
stroke_width = h_o.radius * 0.33
h_o.io.puts('<polyline points="%s" stroke="%s" stroke-width="%f" fill="none"/>' % [coord_a.join(','), stroke_color, stroke_width])
end
end
HexdotGenerator.new(file: "hexdot4.svg").start do |h_o|
h_o.col.times do |x1|
next if x1.odd?
next if x1 + 2 >= h_o.col
coord_a = []
h_o.row.times do |y1|
x = x1
y = y1
x_coord, y_coord = h_o.send(:coord, x, y)
coord_a << x_coord << y_coord
end
(h_o.row - 1).downto(0) do |y1|
x = x1 + 1
y = y1
x_coord, y_coord = h_o.send(:coord, x, y)
coord_a << x_coord << y_coord
end
stroke_color = "red"
stroke_width = h_o.radius * 0.33
h_o.io.puts('<polygon points="%s" stroke="%s" stroke-width="%f" fill="none"/>' % [coord_a.join(','), stroke_color, stroke_width])
end
if h_o.col.even?
x1 = h_o.col - 2
coord_a = []
h_o.row.times do |y1|
x = x1
y = y1
x_coord, y_coord = h_o.send(:coord, x, y)
coord_a << x_coord << y_coord
end
(h_o.row - 1).downto(0) do |y1|
x = x1 + 1 - (y1.odd? ? 1 : 0)
y = y1
x_coord, y_coord = h_o.send(:coord, x, y)
coord_a << x_coord << y_coord
end
stroke_color = "blue"
stroke_width = h_o.radius * 0.33
h_o.io.puts('<polygon points="%s" stroke="%s" stroke-width="%f" fill="none"/>' % [coord_a.join(','), stroke_color, stroke_width])
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment