From: Tim Hunter Date: 2008-02-20T08:56:15+09:00 Subject: Re: RMagick and circle problem shawn bright wrote: > Hello all, i am back with this one. > > my problem is that i am trying to draw a line on a circle that will > indicate a certain angle. > kinda like the hands on a clock. I have a line image that i rotate > around and then superimpose upon the circle image that i draw. > > The problem is that when the line image is rotated, it is shorter than > the circle. > > here is the code. > #!/usr/bin/ruby > > require 'RMagick' > > def gps_image(r) > # fetches the image file > > gps_image = Magick::Image.read('line_stop.png').first > gps_image.background_color = 'none' > > angle = 45 > gps_image.rotate!(angle) > > factor = (r.to_i * 2) > gps_image.crop_resized!(factor, factor, Magick::CenterGravity) > gps_image.write("site.site_name.png") > > return gps_image > end > > def circle_image > r = 45 > #start with a bare canvas (square 2 times the radius of circle) the > extra two pixels is to not cut any of the border > canvas = Magick::Image.new((2 * r) +2, (2*r) +2, > Magick::HatchFill.new('transparent', 'transparent')) > > # draw the circle > gc = Magick::Draw.new > gc.stroke('red') > gc.stroke_width(1) > # fill in the inside > color = 'blue' > gc.fill(color) > gc.fill_opacity(0.3) > gc.circle(r, r, 0, r) > > # put our circle on the canvas > image = gc.draw(canvas) > > # place the line for gps circles > gps_image = gps_image(r) > canvas.composite!(gps_image, 0, 0, Magick::OverCompositeOp) > > # write the image out as a file > canvas.write("circle.png") > end > > circle_image() > > Everything is ok if the image is 90, 180, 270, or 0 degrees, but the > more i stray toward 45 degrees or so, the smaller the line comes out > on the image. > > the image used here ( line_stop.png) is just a transparent image with > a line drawn on it in the middle. ( my clock hand ) > > thanks for any tips. > > shawn > Looks like you're expecting the image produced by rotate! to be the same size as the input image. The rotate! method doesn't just rotate the line, it rotates the entire image. When you rotate the image by some angle that's not a multiple of 90 degrees, the resulting image is going to be wider than the input image. The resize part of crop_resized shrinks the image to fit. Instead of rotating the clock hand and then compositing the resulting image over the circle image, it might be simpler to use Draw's composite method to composite the clock hand over the circle with a suitable rotation. Since rotation always rotates around the origin, use translate to move the origin to the center of the circle. Here's an example. require 'RMagick' HAND_WIDTH = 5 def draw_hand(w) img = Magick::Image.new(w, HAND_WIDTH) {self.background_color = "none"} gc = Magick::Draw.new gc.stroke_linecap "round" gc.stroke "blue" gc.stroke_width HAND_WIDTH gc.line 0, HAND_WIDTH/2.0, w-(HAND_WIDTH*3)/4, HAND_WIDTH/2.0 gc.draw img img end hand = draw_hand(100) def clock(side, hand, angle) img = Magick::Image.new(side+5, side+5) gc = Magick::Draw.new gc.stroke "red" gc.fill "none" gc.stroke_width 5 gc.circle side/2+2.5, side/2+2.5, side, side/2 gc.translate((side+2)/2, (side+2)/2) gc.rotate angle gc.composite 0, 0, 0, 0, hand gc.draw img img end clock = Magick::ImageList.new 8.times do |n| clock << clock(200, hand, n*45) end clock.delay = 25 clock.animate -- RMagick: http://rmagick.rubyforge.org/ RMagick 2: http://rmagick.rubyforge.org/rmagick2.html