Class: Framecurve::Curve

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/framecurve/curve.rb

Overview

Represents a curve file with comments and frame correlation records

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*elements) ⇒ Curve

Returns a new instance of Curve.



9
10
11
12
13
14
# File 'lib/framecurve/curve.rb', line 9

def initialize(*elements)
  @elements = []
  elements.flatten.each do | e |
    @elements.push(e)
  end
end

Instance Attribute Details

#filenameObject

If this curve has been generated or parsed from a file, the parser will preserve the filename here



7
8
9
# File 'lib/framecurve/curve.rb', line 7

def filename
  @filename
end

Instance Method Details

#[](at) ⇒ Object

Get a record by offset (line number 0-based)



70
71
72
# File 'lib/framecurve/curve.rb', line 70

def [](at)
  @elements[at]
end

#any_tuples?Boolean

Tells whether the curve has any tuples at all

Returns:

  • (Boolean)


75
76
77
# File 'lib/framecurve/curve.rb', line 75

def any_tuples?
  @elements.any? {|e| e.tuple? }
end

#comment!(text) ⇒ Object

Adds a comment line



41
42
43
# File 'lib/framecurve/curve.rb', line 41

def comment!(text)
  @elements.push(Framecurve::Comment.new(text.strip))
end

#eachObject

Iterates over all the elements in the curve



29
30
31
# File 'lib/framecurve/curve.rb', line 29

def each
  @elements.each(&Proc.new)
end

#each_commentObject

Iterates over all the comments in the curve



34
35
36
37
38
# File 'lib/framecurve/curve.rb', line 34

def each_comment
  @elements.each do | e |
    yield(e) if e.comment?
  end
end

#each_defined_tupleObject

Yields each tuple that is defined by this framecurve in succession. For example, if the curve contains tuples at (1, 123.45) and (10, 167.89) this method will yield 10 times for each defined integer frame value



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/framecurve/curve.rb', line 92

def each_defined_tuple
  tuples = select{|e| e.tuple? }
  tuples.each_with_index do | tuple, idx |
    next_tuple = tuples[idx + 1]
    if next_tuple.nil?
      yield(tuple)
    else # Apply linear interpolation
      dt = next_tuple.at - tuple.at
      if dt == 1
        yield(tuple)
      else
        dy = next_tuple.value - tuple.value
        delta = dy / dt
        dt.times do | increment |
          value_inc = delta * increment
          yield(Framecurve::Tuple.new(tuple.at + increment, tuple.value + value_inc))
        end
      end
    end
  end
end

#each_tupleObject

Iterates over all the tuples in the curve



17
18
19
20
21
# File 'lib/framecurve/curve.rb', line 17

def each_tuple
  @elements.each do | e |
    yield(e) if e.tuple?
  end
end

#empty?Boolean

Tells whether the curve contains any elements

Returns:

  • (Boolean)


65
66
67
# File 'lib/framecurve/curve.rb', line 65

def empty?
  @elements.empty?
end

#lengthObject

Returns the number of lines in this curve file



60
61
62
# File 'lib/framecurve/curve.rb', line 60

def length
  @elements.size
end

#only_tuplesObject

Return the tuples in this curve



24
25
26
# File 'lib/framecurve/curve.rb', line 24

def only_tuples
  @elements.select{|e| e.tuple? }
end

#to_materialized_curveObject

Returns a new curve with the same data with all the intermediate frames interpolated properly and all the comments except for the preamble removed



81
82
83
84
85
86
87
# File 'lib/framecurve/curve.rb', line 81

def to_materialized_curve
  c = self.class.new
  c.comment! "http://framecurve.org/specification-v1"
  c.comment! "at_frame\tuse_frame_of_source"
  each_defined_tuple {|t|  c.tuple!(t.at, t.value) }
  return c
end

#tuple!(at, value) ⇒ Object

Adds a tuple



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/framecurve/curve.rb', line 46

def tuple!(at, value)
  t = Framecurve::Tuple.new(at.to_i, value.to_f)
  # Validate for sequencing
  if any_tuples?
    last_frame = only_tuples[-1].at
    if t.at <= last_frame
      raise Framecurve::Malformed, "Cannot add a frame that comes before or at the same frame as the previous one (%d after %d)" % [t.at, last_frame]
    end
  end
  
  @elements.push(t)
end