require "pp" # A tiny ruby script to design and test the implementation of the arc-support class Numeric # -1 if the number < 0, 1 if number >= 0 def sign return 0 if self == 0 (self < 0) ? -1 : 1 end end class CircleTest include Math def init @pixels = [] @tool_position = [14,14] 30.times { @pixels << '.'*30 } end def plot_pixel(x,y, c) return if x<0 || y<0 || x>29 || y > 29 @pixels[y] = @pixels[y][0..x][0..-2]+c+@pixels[y][(x+1)..-1] end def show @pixels.each do |line| puts line.gsub('.','. ').gsub('0','0 ').gsub('1','1 ').gsub('2','2 ').gsub('X','X ').gsub('o','o ') end end # dP[x+1,y]: 1 + 2 x # dP[x-1,y]: 1 - 2 x # dP[x, y+1]: 1 + 2 y # dP[x, y-1]: 1 - 2 y # dP[x+1, y+1]: 2 (1 + x + y) # dP[x+1, y-1]: 2 (1 + x - y) # dP[x-1, y-1]: 2 (1 - x - y) # dP[x-1, y+1]: 2 (1 - x + y) # dP[x+a, y+b]: |dx| - 2*dx*x + |dy| + 2*dy*y # Algorithm from the wikipedia aricle on the Midpoint circle algorithm. def raster_circle(radius) f = 1-radius ddF_x = 1 ddF_y = -2*radius x = 0 y = radius while x<=y if f>0 y -= 1 ddF_y += 2 f += ddF_y end x += 1 ddF_x += 2 f += ddF_x plot_pixel(x+14,-y+14,'X') end x += 1 ddF_x += 2 f += ddF_x while y>0 if f<0 x += 1 ddF_x += 2 f += ddF_x end y -= 1 ddF_y += 2 f += ddF_y plot_pixel(x+14,-y+14,'o') end end # An "ideal" arc. Computationally expensive, but always pure def pure_arc(theta, segment, angular_direction, radius) var = [(sin(theta)*(radius)), (cos(theta)*(radius))] error_sum = 0.0 error_count = 0.0 max_error = 0.0 (PI*2*radius).ceil.times do if var[0].abs 0 plot_pixel(x+14, -y+14, "012"[i%3].chr) else plot_pixel(x+14, -y+14, "X") end dx = (y==0) ? angular_direction : y.sign*angular_direction dy = (x==0) ? angular_direction : -x.sign*angular_direction if x.abs=tx.abs) && (y.abs>=ty.abs) i += 1 end puts "Target #{[tx,ty].inspect}" plot_pixel(tx+14, -ty+14, "o") pp [x,y] puts "Diameter: #{max_x-min_x}" end end test = CircleTest.new test.init test.arc_clean(0, -Math::PI, 5) test.show