Categories

Posts in this category

Mon, 07 Sep 2009

How to Plot a Segment of a Circle with SVG


Permanent link
circle with differently colored segments

(SVG version)

I wanted to generate some pie charts with SVG (for SVG::Plot), and a search on the Internet quickly showed that I need paths for that. But the exact usage remained unclear to me until I read the specs and did some experimenting.

The way to go is:

  1. Move to (M) the center of the circle
  2. Line to (l) the starting point of the arc
  3. Arc to (A) the end point of the arc
  4. Close the path (z)
    1. The start and end point of the arc can be calculated as

      x = center_x + radius * cos(angle)
      y = center_y + radius * sin(angle)
      

      The parameters to the A command in the path are rx, ry, axis-rotation large-arc-flag sweep-flag x y.

      For our purposes rx and ry need to be just the radius of the circle, large-arc-flag is 1 if the difference between start angle and end angle is larger than pi (or 180°). sweep-flag is 1 if we assume that the start angle is smaller than the end angle (and thus, since the SVG coordinate system has the positive y axis downwards, plot clockwise). x and y are the coordinates of the end point.

      The code I used to generate the SVG above is (in Perl 6, using Carl Mäsak's SVG module):

      use v6;
      BEGIN { @*INC.push: 'src/svg/lib' }
      use SVG;
      
      sub arc($cx = 100, $cy = 100, $r = 50, :$start, :end($phi), :$color = 'red') {
          my @commands = 'M', $cx, $cy,
                  'l', $r * cos($start), $r * sin($start),
                  'A', $r, $r, 0,  + ($phi - $start > pi), 1,
                          $cx + $r * cos($phi), $cy + $r * sin($phi), "z";
      
          my $c = join ' ', @commands;
          return 'g' => [
              :stroke<none>,
              :fill($color),
              path => [ :d($c) ],
          ];
      }
      
      
      say SVG.serialize(
          'svg' => [
              :width(200), :height(200),
              'xmlns' => 'http://www.w3.org/2000/svg',
              'xmlns:svg' => 'http://www.w3.org/2000/svg',
              'xmlns:xlink' => 'http://www.w3.org/1999/xlink',
              arc(:color<blue>, :start(0),    :end(pi/3)),
              arc(:color<red>,  :start(pi/3), :end(3 * pi / 2)),
              arc(:color<yellow>, :start(3 * pi / 2), :end(0)),
          ]);
      

      The only syntactic feature here worth explaining is that + ( $thing > pi ) returns 1 if $thing is larger than pi and 0 otherwise. Everything else should be straight forward.

[/perl-6] Permanent link