module Prawn::Graphics

Public Instance Methods

arc_around(center, options) click to toggle source

options must include :radius, :start_angle, and :end_angle startAngle and endAngle are in degrees

0 degrees is directly right and 90 degrees is straight up arc will be drawn counterclockwise from startAngle to endAngle

# File lib/prawn_shapes/arc.rb, line 79
def arc_around(center, options)
  open_curve(arc_vertices(center, options))
end
closed_curve(vertices) click to toggle source

vertices is an array of hashes containing :vertex and optional :handle1 and :handle2 elements

# File lib/prawn_shapes/arc.rb, line 101
def closed_curve(vertices)
  return if vertices.empty?
  vertices = vertices.dup
  origin = vertices.shift
  move_to(origin[:point])
  previous_handle2 = origin[:handle2]
  vertices.each do |vertex|
    curve_to(vertex[:point],
             :bounds => [previous_handle2 || vertex[:point],
                         vertex[:handle1] || vertex[:point]])
    previous_handle2 = vertex[:handle2]
  end
  curve_to(origin[:point],
           :bounds => [previous_handle2 || origin[:point],
                       origin[:handle1] || origin[:point]])
end
half_circle(center, options) click to toggle source

options must include :radius and :side side is either :left or :right see pie_slice for explanation of optional :stroke_both_sides option

# File lib/prawn_shapes/arc.rb, line 8
def half_circle(center, options)
  case options[:side]
  when :left
    start_angle = 90
    end_angle = 270
  when :right
    start_angle = 270
    end_angle = 90
  end
  pie_slice(center,
            :radius => options[:radius],
            :start_angle => start_angle,
            :end_angle => end_angle,
            :stroke_both_sides => options[:stroke_both_sides])
end
half_star(point, options) click to toggle source
# File lib/prawn_shapes/star.rb, line 8
def half_star(point, options)
  points = star_points(point, options)
  case options[:side]
  when :left
    points.slice!(1..4)
  when :right
    points.slice!(6..9)
  end
  polygon(*points)
end
open_curve(vertices) click to toggle source

vertices is an array of hashes containing :vertex and optional :handle1 and :handle2 elements

# File lib/prawn_shapes/arc.rb, line 85
def open_curve(vertices)
  return if vertices.empty?
  vertices = vertices.dup
  origin = vertices.shift
  move_to(origin[:point])
  previous_handle2 = origin[:handle2]
  vertices.each do |vertex|
    curve_to(vertex[:point],
             :bounds => [previous_handle2 || vertex[:point],
                         vertex[:handle1] || vertex[:point]])
    previous_handle2 = vertex[:handle2]
  end
end
pie_slice(center, options) click to toggle source

options must include :radius, :start_angle, and :end_angle startAngle and endAngle are in degrees if an optional :stroke_both_sides option is true, then both sides of the slice will be included for stroking. the default is to just stroke one side since this will tend to be used to build up an entire circle, and if both sides were stroked, then we would get double-stroked lines where two pie slices shared a (not usually noticeable, but would be if transparency were used)

0 degrees is directly right and 90 degrees is straight up arc will be drawn counterclockwise from startAngle to endAngle

# File lib/prawn_shapes/arc.rb, line 63
def pie_slice(center, options)
  vertices = arc_vertices(center, options)
  vertices.unshift(:point => center)
  if options[:stroke_both_sides]
    closed_curve(vertices)
  else
    open_curve(vertices)
  end
end
quarter_circle(center, options) click to toggle source

options must include :radius and :quadrant quadrant is 1, 2, 3, or 4 see pie_slice for explanation of optional :stroke_both_sides option

# File lib/prawn_shapes/arc.rb, line 29
def quarter_circle(center, options)
  case options[:quadrant]
  when 1
    start_angle = 0
    end_angle = 90
  when 2
    start_angle = 90
    end_angle = 180
  when 3
    start_angle = 180
    end_angle = 270
  when 4
    start_angle = 270
    end_angle = 360
  end
  pie_slice(center,
            :radius => options[:radius],
            :start_angle => start_angle,
            :end_angle => end_angle,
            :stroke_both_sides => options[:stroke_both_sides])
end
star(point, options) click to toggle source
# File lib/prawn_shapes/star.rb, line 3
def star(point, options)
  x, y = point
  polygon(*star_points(point, options))
end

Private Instance Methods

arc_vertices(center, options) click to toggle source
# File lib/prawn_shapes/arc.rb, line 127
def arc_vertices(center, options)
  radius = options[:radius]
  start_degrees = options[:start_angle]
  end_degrees = options[:end_angle]
  return [] if start_degrees == end_degrees

  overall_start_angle = (start_degrees % 360.0).to_radians
  overall_end_angle = (end_degrees % 360.0).to_radians

  # if the angles are now equal, when they weren't before, then
  # they describe an entire circle
  if overall_start_angle == overall_end_angle
    overall_start_angle = 0
    overall_end_angle = 2.0 * Math::PI
  end

  overall_end_angle = overall_end_angle + 2.0 * Math::PI if overall_end_angle < overall_start_angle

  delta = overall_end_angle - overall_start_angle
  quadrants = (delta / (Math::PI * 0.5)).ceil

  vertices = []
  quadrants.times do |i|
    start_angle = overall_start_angle + Math::PI * 0.5 * i

    if i == quadrants - 1
      end_angle = overall_end_angle
    else
      end_angle = start_angle + Math::PI * 0.5
    end

    delta = end_angle - start_angle
    handle_multiplier = KAPPA * delta / (Math::PI * 0.5) * radius

    vertex = {}
    point = [Math.cos(start_angle), Math.sin(start_angle)]
    vertex[:point] = [center[0] + radius * point[0],
                      center[1] + radius * point[1]]
    handle = point.unit_perpendicular_vector(:counter_clockwise => false)
    vertex[:handle2] = [vertex[:point][0] + handle_multiplier * handle[0],
                        vertex[:point][1] + handle_multiplier * handle[1]]

    vertices << vertex

    vertex = {}
    point = [Math.cos(end_angle), Math.sin(end_angle)]
    vertex[:point] = [center[0] + radius * point[0],
                      center[1] + radius * point[1]]
    handle = point.unit_perpendicular_vector(:counter_clockwise => true)
    vertex[:handle1] = [vertex[:point][0] + handle_multiplier * handle[0],
                        vertex[:point][1] + handle_multiplier * handle[1]]
    vertices << vertex
  end
  vertices
end
star_points(point, options) click to toggle source

radius is the horizontal half-width of the star (the star is the hand-drawn type that looks more natural to the eye, so it does not fit perfectly into a circle)

# File lib/prawn_shapes/star.rb, line 29
def star_points(point, options)
  x, y = point
  radius = options[:radius]
  y = y + radius * 0.05
  points = []
  points << [x,                 y + radius * 0.9]
  points << [x + 0.25 * radius, y + 0.2 * radius]
  points << [x + radius,        y + 0.2 * radius]
  points << [x + 0.4 * radius,  y - 0.2 * radius]
  points << [x + 0.7 * radius,  y - 1.0 * radius]
  points << [x,                 y - 0.5 * radius]
  points << [x - 0.7 * radius,  y - 1.0 * radius]
  points << [x - 0.4 * radius,  y - 0.2 * radius]
  points << [x - radius,        y + 0.2 * radius]
  points << [x - 0.25 * radius, y + 0.2 * radius]
  points
end