Class: Spliner::Spliner

Inherits:
Object
  • Object
show all
Defined in:
lib/spliner/spliner.rb

Overview

Spliner::Spliner provides cubic spline interpolation based on provided key points on a X-Y curve.

Example

require 'spliner'
# Initialize a spline interpolation with x range 0.0..2.0
my_spline = Spliner::Spliner.new [0.0, 1.0, 2.0], [0.0, 1.0, 0.5]
# Perform interpolation on 31 values ranging from 0..2.0
x_values = (0..30).map {|x| x / 30.0 * 2.0 }
y_values = x_values.map {|x| my_spline[x] }

Algorithm based on en.wikipedia.org/wiki/Spline_interpolation

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key_points, options) ⇒ Spliner #initialize(x, y, options) ⇒ Spliner

Creates a new Spliner::Spliner object to interpolate between the supplied key points.

The key points shoul be in increaing X order. When duplicate X values are encountered, the spline is split into two or more discontinuous sections.

The extrapolation method may be :linear by default, using a linear extrapolation at the curve ends using the curve derivative at the end points. The :hold method will use the Y value at the nearest end point of the curve.

Overloads:

  • #initialize(key_points, options) ⇒ Spliner

    Parameters:

    • key_points (Hash{Float => Float})

      keys are X values in increasing order, values Y

    • options (Hash)

    Options Hash (options):

    • :extrapolate (Range, String) — default: '0%'

      either a range or percentage, eg ‘10.0%’

    • :emethod (Symbol) — default: :linear

      extrapolation method

  • #initialize(x, y, options) ⇒ Spliner

    Parameters:

    • x (Array(Float), Vector)

      the X values of the key points

    • y (Array(Float), Vector)

      the Y values of the key points

    • options (Hash)

    Options Hash (options):

    • :extrapolate (Range, String) — default: '0%'

      either a range or percentage, eg ‘10.0%’

    • :emethod (Symbol) — default: :linear

      extrapolation method



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/spliner/spliner.rb', line 47

def initialize(*param)
  # sort parameters from two alternative initializer signatures
  x, y = nil
  case param.first
  when Array, Vector
    xx,yy, options = param
    x = xx.to_a
    y = yy.to_a
  else
    points, options = param
    x = points.keys
    y = points.values
  end
  options ||= {}

  @sections = split_at_duplicates(x).map {|slice| SplinerSection.new x[slice], y[slice] }

  # Handle extrapolation option parameter
  options[:extrapolate].tap do |ex|
    case ex
    when /^\d+(\.\d+)?\s?%$/
      percentage = ex[/\d+(\.\d+)?/].to_f
      span = x.last - x.first
      extra = span * percentage * 0.01
      @range = (x.first - extra)..(x.last + extra)
    when Range
      @range = ex
    when nil
      @range = x.first..x.last
    else
      raise 'Unable to use extrapolation parameter'
    end
  end
  @extrapolation_method = options[:emethod] || :linear
end

Instance Attribute Details

#rangeObject (readonly)

Returns the value of attribute range.



20
21
22
# File 'lib/spliner/spliner.rb', line 20

def range
  @range
end

Instance Method Details

#get(v) ⇒ Object Also known as: []

returns an interpolated value



93
94
95
96
97
98
99
100
101
102
# File 'lib/spliner/spliner.rb', line 93

def get(v)
  i = @sections.find_index {|section| section.range.member? v }
  if i
    @sections[i].get v
  elsif range.member? v
    extrapolate(v)
  else
    nil
  end
end

#sectionsObject

The number of non-continuous sections used



107
108
109
# File 'lib/spliner/spliner.rb', line 107

def sections
  @sections.size
end