Ruby On Rails, Design, Simplicity, Web 2.0, Ajax, Mac and Tons of Pizza.

Mar 05

RVG and SVuGy: create vector graphic with Ruby

Posted by Sandro Paganotti in Ruby on Rails - 4 comments digg this add to delicious

Today we’re going to discover two ways to create vectorial graphic with Ruby;

RVG

The first way is called RVG and it’s part of the well-known Rmagick library. With RVG you can create custom shapes and then render them to images. Here there is a simple example (taken from the RMagic docs and modified a bit):


require 'rvg/rvg'

target = Magick::RVG.new.viewbox(0,0,200,200) do |targ|
    targ.g.styles(:stroke_width=>20, :stroke=>'#ff5600', :fill=>'#abd600') do |grp|
        grp.circle(90, 100, 100)
        grp.circle(60, 100, 100)
        grp.circle(30, 100, 100)
    end
end

rvg = Magick::RVG.new(258, 100) do |canvas|
    canvas.use(target, 0, 0, 100, 100)
    canvas.use(target, 100, 16.6667, 66.7, 66.7)
    canvas.use(target, 166.6667, 25, 50, 50)
    canvas.use(target, 216.6667, 30, 40, 40)
end

rvg.draw.write('nested_rvg.gif')

And this is its output:

SvuGy

This library acts in a very similar way with the small but noticeable difference that its output is not an image but a pure .svg file. Here is the code to product the same sample as above ( I know, it is not so DRY but i didn’t find smarter ways to do this, in part due to a lack of documentation):



require 'SVuGy'

drawing1 = SVuGy::Document.new(530, 200) do

    tri = group.style(:stroke_width=>20, :stroke=>'#ff5600', :fill=>'#abd600'){
      el2 = ellipse(100, 100, 90, 90)
      el1 = ellipse(100, 100, 60, 60)
      el0 = ellipse(100, 100, 30, 30)
    }

    tri2 = group.style(:stroke_width=>20, :stroke=>'#ff5600', :fill=>'#abd600').translate(200,30).scale(0.66){
      el2 = ellipse(100, 100, 90, 90)
      el1 = ellipse(100, 100, 60, 60)
      el0 = ellipse(100, 100, 30, 30)
    }

    tri3 = group.style(:stroke_width=>20, :stroke=>'#ff5600', :fill=>'#abd600').translate(330,50).scale(0.5){
      el2 = ellipse(100, 100, 90, 90)
      el1 = ellipse(100, 100, 60, 60)
      el0 = ellipse(100, 100, 30, 30)
    }

    tri4 = group.style(:stroke_width=>20, :stroke=>'#ff5600', :fill=>'#abd600').translate(430,60).scale(0.4){
      el2 = ellipse(100, 100, 90, 90)
      el1 = ellipse(100, 100, 60, 60)
      el0 = ellipse(100, 100, 30, 30)
    }

end

print drawing1.to_svg

And here you can admire the generated SVG (download the file):

Considerations

Now that I found out this library I’m thinking about an hypothetic world where these two libraries works with the same syntax letting you generate SVG if the browser support this format and otherwise printing a simple image. Another big improvement could be create a SVG to RVG parser, by this way you can import complex SVGs generated with WYSIWYG programs and then add to them dynamic functionalities.

Comments

  • Timothy Hunter

    Posted on March 06

    I'm glad you like RVG! I have an SVG-to-RVG parser that I wrote to convert tests from the SVG 1.1 Test suite into tests for RVG. I will be happy to send it to you. If you're interested please email me at rmagick AT rubyforge DOT org.
  • Sandro Paganotti

    Posted on March 06

    RVG is really great ! Thank you Timothy for the amazing work you did with RVG :D
  • Aaron Blohowiak

    Posted on March 10

    You do know that RMagick can read SVG as an input format, and then convert it to whatever you need, right? --Aaron
  • Martin Dürst

    Posted on March 31

    Wow, the first blog entry about SVuGy! I have DRYed up your example a bit, see below. The code uses features of both SVuGy and Ruby, that's the fun of an internal DSL. If it uses different abstractions from those you had in mind, please feel free to rewrite it. If you have any problems, please just contact me. The main difficulty I had when writing the example was to remember what was available in the 0.03 version and what not. Since our SVGOpen2007 paper, SVuGy has gained quite a bit more functionality, and we hope that we can publish a new version soon. And here's the new code: # example from Sandro Paganotti # http://www.railsonwave.com/railsonwave/2008/3/5/rvg-and-svugy-create-vectorial-graphic-with-ruby # DRYed up by Martin Duerst require 'SVuGy' drawing = SVuGy::Document.new(530, 200) do circles = defs { g(:circles) { circle 0, 0, 90 circle 0, 0, 60 circle 0, 0, 30 } } g.style(:stroke_width=>20, :stroke=>'#ff5600', :fill=>'#abd600') { x = 0 [1, 0.66, 0.5, 0.4].each do |s| x += 100*s use(:circles).translate(x, 100).scale(s) x += 100*s end } end print drawing.to_svg

Post a comment

Categories:

Tags:

Powered by Mephisto, Valid XHTML 1.1, Valid CSS - Supported by Wave Factory