Class: PDF::Charts::StdDev

### Home Classes Methods

### In Files

- lib/pdf/charts/stddev.rb

### Parent

Object

### Namespace

- CLASS PDF::Charts::StdDev::Label
- CLASS PDF::Charts::StdDev::Marker
- CLASS PDF::Charts::StdDev::Scale

### Methods

- ::new
- #render_on

### Files

- ChangeLog

### Class/Module Index

Quicksearch

- PDF
- PDF::Charts
- PDF::Charts::StdDev
- PDF::Charts::StdDev::Label
- PDF::Charts::StdDev::Marker
- PDF::Charts::StdDev::Scale
- PDF::Math
- PDF::QuickRef
- PDF::SimpleTable
- PDF::SimpleTable::Column
- PDF::SimpleTable::Column::Heading
- PDF::TechBook
- PDF::TechBook::TagTocDots
- PDF::TechBook::TagXref
- PDF::Writer
- PDF::Writer::ARC4
- PDF::Writer::Complex
- PDF::Writer::External
- PDF::Writer::FontMetrics
- PDF::Writer::Graphics
- PDF::Writer::Graphics::ImageInfo
- PDF::Writer::Graphics::ImageInfo::Formats
- PDF::Writer::Graphics::ImageInfo::Type
- PDF::Writer::Lang
- PDF::Writer::Lang::EN
- PDF::Writer::OHash
- PDF::Writer::Object
- PDF::Writer::Object::Action
- PDF::Writer::Object::Annotation
- PDF::Writer::Object::Catalog
- PDF::Writer::Object::Contents
- PDF::Writer::Object::Destination
- PDF::Writer::Object::Encryption
- PDF::Writer::Object::Font
- PDF::Writer::Object::FontDescriptor
- PDF::Writer::Object::FontEncoding
- PDF::Writer::Object::Info
- PDF::Writer::Object::Outline
- PDF::Writer::Object::Outlines
- PDF::Writer::Object::Pages
- PDF::Writer::Object::Procset
- PDF::Writer::Object::ViewerPreferences
- PDF::Writer::OffsetReader
- PDF::Writer::PolygonPoint
- PDF::Writer::State
- PDF::Writer::StateStack
- PDF::Writer::StrokeStyle

No matching classes.

# PDF::Charts::StdDev

Creates a standard deviation chart. This is a type of chart that is effective for the display of survey results or other data that can easily be measured in terms of the average and the standard deviation from that average.

The scale of responses is the vertical scale; the average data points and standard deviation values are the horizontal scale.

### Constants

DataPoint

  A data element.

### Attributes

bar[RW]

The standard deviation bar. A line will be drawn through the dot marker (if drawn) from the upper to lower standard deviation. If `nil`, the line will not be drawn. This is a PDF::Charts::StdDev::Marker object.

data[R]

The data used to generate the standard deviation chart. This is an array of DataPoint objects, each containing a `label`, an `average`, and the `stddev` (standard deviation) from that average.

datapoint_width[RW]

The width of a single datapoint.

dot[RW]

The dot marker. A filled circle will be drawn with this information. If `nil`, the dot will not be drawn. This is a PDF::Charts::StdDev::Marker object.

height[RW]

The height of the chart in PDF user units. Default 200 units.

inner_borders[RW]

The inner border style. If `nil`, no inner borders are drawn. This is a PDF::Charts::StdDev::Marker object.

label[RW]

The label style of the labels if they are displayed. This must be a PDF::Charts::StdDev::Label object.

leading_gap[RW]

The minimum gap between the chart and the bottom of the page, in PDF user units.

lower_crossbar[RW]

The lower crossbar. A line will be drawn across the bottom of the standard deviation bar to the width of the dot marker. If dot is `nil`, then the line will be twice as wide as it is thick. If `nil`, the lower crossbar will not be drawn. This is a PDF::Charts::StdDev::Marker object.

maximum_width[RW]

The maximum width of the chart in PDF user units. Default 500 units.

outer_borders[RW]

The outer border style. If `nil`, no inner borders are drawn. This is a PDF::Charts::StdDev::Marker object.

scale[RW]

The scale of the chart. All values must be within this range. This will be a Scale object. It defaults to a scale of 0..6 with a step of 1.

show_labels[RW]

This will be `true` if labels are to be displayed.

upper_crossbar[RW]

The upper crossbar. A line will be drawn across the top of the standard deviation bar to the width of the dot marker. If dot is `nil`, then the line will be twice as wide as it is thick. If `nil`, the upper crossbar will not be drawn. This is a PDF::Charts::StdDev::Marker object.

### Public Class Methods

new() click to toggle source

    # File lib/pdf/charts/stddev.rb, line 109
    def initialize
      @data                       = []

      @scale                      = Scale.new do |scale|
        scale.range               = 0..6
        scale.step                = 1
        scale.style               = PDF::Writer::StrokeStyle.new(0.25)
        scale.show_labels         = false
        scale.label               = Label.new do |label|
          label.text_size         = 8
          label.text_color        = Color::RGB::Black
          label.pad               = 2
          label.decimal_precision = 1
        end
      end
      @leading_gap              = 10
      @show_labels              = true
      @label                    = Label.new do |label|
        label.height            = 25
        label.background_color  = Color::RGB::Black
        label.text_color        = Color::RGB::White
        label.text_size         = 12
      end

      @outer_borders            = Marker.new do |marker|
        marker.style            = PDF::Writer::StrokeStyle.new(1.5)
        marker.color            = Color::RGB::Black
      end
      @inner_borders            = nil

      @dot                      = Marker.new do |marker|
        marker.style            = PDF::Writer::StrokeStyle.new(5)
        marker.color            = Color::RGB::Black
      end
      @bar                      = Marker.new do |marker|
        marker.style            = PDF::Writer::StrokeStyle.new(0.5)
        marker.color            = Color::RGB::Black
      end
      @upper_crossbar           = Marker.new do |marker|
        marker.style            = PDF::Writer::StrokeStyle.new(1)
        marker.color            = Color::RGB::Black
      end
      @lower_crossbar           = Marker.new do |marker|
        marker.style            = PDF::Writer::StrokeStyle.new(1)
        marker.color            = Color::RGB::Black
      end

      @height                   = 200
      @maximum_width            = 500
      @datapoint_width          = 35

      yield self if block_given?
    end

### Public Instance Methods

render_on(pdf) click to toggle source

Draw the standard deviation chart on the supplied PDF document.

    # File lib/pdf/charts/stddev.rb, line 219
    def render_on(pdf)
      raise TypeError, PDF::Writer::Lang[:charts_stddev_data_empty] if @data.empty?
      data = @data.dup
      leftover_data = nil

      loop do
        # Set up the scale information.
        scale = []

        (@scale.first + @scale.step).step(@scale.last, @scale.step) do |ii|
          scale << "%01.#{@scale.label.decimal_precision}f" % ii
        end

        scales = PDF::Writer::OHash.new
        scale.each_with_index do |gg, ii|
          scales[ii] = OpenStruct.new
          scales[ii].value = gg
        end

        # Add information about the scales' locations to the scales
        # hash. Note that the count is one smaller than it should be, so we're
        # increasing it. The first scale is the bottom of the chart.
        scale_count = scale.size + 1

        label_height_adjuster = 0
        label_height_adjuster = @label.height if @show_labels

        chart_area_height = @height - label_height_adjuster
        scale_height   = chart_area_height / scale_count.to_f

        scales.each_key do |index|
          this_height = scale_height * (index + 1) + @label.height
          scales[index].line_height = this_height
          if @scale.show_labels
            scales[index].label_height = this_height -
            (@scale.label.text_size / 3.0)
          end
        end

        # How many sections do we need in this chart, and how wide will it
        # need to be?
        chunk_width = @datapoint_width
        num_chunks  = data.size
        widest_scale_label = 0

        if @scale.show_labels
          scales.each_value do |scale|
            this_width = pdf.text_width(scale.value, @scale.label.text_size)
            widest_scale_label = this_width if this_width > widest_scale_label
          end
        end

        chart_width = chunk_width * num_chunks
        total_width = chart_width + widest_scale_label + @scale.label.pad

          # What happens if the projected width of the chart is too big?
          # Figure out how to break the chart in pieces.
        if total_width > @maximum_width
          max_column_count = 0
          base_width = widest_scale_label + @scale.label.pad
          (1..(num_chunks + 1)).each do |ii|
            if (base_width + (ii * chunk_width)) > @maximum_width
              break
            else
              max_column_count += 1
            end
          end

          leftover_data = data.slice!(max_column_count, -1)

          num_chunks  = data.size
          chart_width = chunk_width * num_chunks
          total_width = chart_width + widest_scale_label + @scale.label.pad
        end

        chart_y = pdf.y - @height + @leading_gap
        chart_y += (@outer_borders.style.width * 2.0) if @outer_borders

        if chart_y < pdf.bottom_margin
          pdf.start_new_page
          chart_y = pdf.y - @height
          chart_y += (@outer_borders.style.width * 2.0) if @outer_borders
        end

        chart_x = pdf.absolute_x_middle - (total_width / 2.0) + widest_scale_label

          # Add labels, if needed.
        if @show_labels
          pdf.save_state
          pdf.fill_color! @label.background_color
          # Draw a rectangle for each label
          num_chunks.times do |ii|
            this_x = chart_x + ii * chunk_width
            pdf.rectangle(this_x, chart_y, chunk_width, @label.height).fill
          end

            # Add a border above the label rectangle.
          if @outer_borders
            pdf.stroke_style! @outer_borders.style
            pdf.line(chart_x, chart_y + @label.height, chart_x + chart_width, chart_y + @label.height).stroke
          end
          pdf.fill_color! @label.text_color

          data.each_with_index do |datum, ii|
            label = datum.label.to_s
            label_width = pdf.text_width(label, @label.text_size)
            this_x = chart_x + (ii * chunk_width) + (chunk_width / 2.0) - (label_width / 2.0)
            this_y = chart_y + (@label.height / 2.0) - (@label.text_size / 3.0)
            pdf.add_text(this_x, this_y, label, @label.text_size)
          end
          pdf.restore_state
        end

        if @inner_borders
          pdf.save_state
          pdf.stroke_color! @inner_borders.color
          pdf.stroke_style! @inner_borders.style
          (num_chunks - 1).times do |ii|
            this_x = chart_x + (ii * chunk_width) + chunk_width
            pdf.line(this_x, chart_y, this_x, chart_y + @height).stroke
          end
          pdf.restore_state
        end

        pdf.save_state
        if @outer_borders
          pdf.stroke_color! @outer_borders.color
          pdf.stroke_style! @outer_borders.style
          pdf.rectangle(chart_x, chart_y, chart_width, @height).stroke
        end

        if @scale.style
          pdf.save_state
          pdf.stroke_style! @scale.style
          scales.each_value do |scale|
            this_y = chart_y + scale.line_height
            pdf.line(chart_x, this_y, chart_x + chart_width, this_y).stroke
          end
          pdf.restore_state
        end

        if @scale.show_labels
          pdf.save_state
          scales.each_value do |scale|
            this_y = chart_y + scale.label_height
            label_width = pdf.text_width(scale.value, @scale.label.text_size)
            this_x = chart_x - label_width - @scale.label.pad
            pdf.fill_color! @scale.label.text_color
            pdf.add_text(this_x, this_y, scale.value, @scale.label.text_size)
          end
          pdf.restore_state
        end

        data.each_with_index do |datum, ii|
          avg_height    = datum.average * scale_height
          stddev_height = datum.stddev * scale_height
          this_y        = chart_y + label_height_adjuster + avg_height
          this_x        = chart_x + (ii * chunk_width) + (chunk_width / 2.0)
          line_top_y    = this_y + (stddev_height / 2.0)
          line_bot_y    = this_y - (stddev_height / 2.0)

            # Plot the dot
          if @dot
            pdf.stroke_color! @dot.color
            pdf.stroke_style! @dot.style
            pdf.circle_at(this_x, this_y, (@dot.style.width / 2.0)).fill
          end

            # Plot the bar
          if @bar
            pdf.stroke_color! @bar.color
            pdf.stroke_style! @bar.style
            pdf.line(this_x, line_top_y, this_x, line_bot_y).stroke
          end

            # Plot the crossbars
          if @upper_crossbar
            if @dot
              cb_width = @dot.style.width
            else
              cb_width = @upper_crossbar.style.width
            end
            pdf.stroke_color! @upper_crossbar.color
            pdf.stroke_style! @upper_crossbar.style
            pdf.line(this_x - cb_width, line_top_y, this_x + cb_width, line_top_y).stroke
          end
          if @lower_crossbar
            if @dot
              cb_width = @dot.style.width
            else
              cb_width = @lower_crossbar.style.width
            end
            pdf.stroke_color! @lower_crossbar.color
            pdf.stroke_style! @lower_crossbar.style

            pdf.line(this_x - cb_width, line_bot_y, this_x + cb_width, line_bot_y).stroke
          end
        end

        pdf.restore_state

        pdf.y = chart_y

        break if leftover_data.nil?

        data = leftover_data
        leftover_data = nil
      end

      pdf.y
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.