Class: TerminalVis::Interpolation::BilinearInterpolation
- Inherits:
-
Object
- Object
- TerminalVis::Interpolation::BilinearInterpolation
- Defined in:
- lib/math/bilinear_interpolation.rb
Overview
math class to interpolate data between a set of points
Instance Attribute Summary collapse
-
#data_set ⇒ DataSet
readonly
private
The used data set.
-
#meta_data ⇒ VisMetaData
readonly
private
The used meta data.
Class Method Summary collapse
-
.apply_bilinear_interpolation(x, y) ⇒ Float
private
singleton method to calculate the bilinear interpolation applies the formula: (1-r)*(1-s)*d(x,y) + r*(1-s)*d(x+1,y) + r*s*d(x+1,y+1) + (1-r)*s*d(x,y+1).
-
.bilinear_interpolation(meta_data, data_set, x, y) ⇒ Float
method for bilinear interpolation.
-
.boundary_case(x, y) ⇒ Float
private
singleton method to apply the interpolation on a boundary case.
-
.calculate_boundary_datapoints(x, y) ⇒ Hash
private
singleton method to calculate the necessary boundary points.
-
.calculate_interpolation_result(r, s, value) ⇒ Float
private
singleton method to calculate the result of the bilinear interpolation.
-
.check_data_range(x, y) ⇒ Object
private
singleton method to check if the provided coordinates (x,y) lie within the data area specified by the meta information.
-
.check_for_upper_boundary(x, y) ⇒ Boolean
private
singleton method to check if the provided coordinates lie on one of the upper dimension boundaries.
-
.coordinate_in_dataset(data_domain, coordinate) ⇒ Boolean
private
singleton method to check if the provided coordinate lies within the given domain of the dataset.
-
.create_data_point(delta_x, delta_y, x, y) ⇒ DataPoint
private
creation of the boundary data points for the bilinear interpolation.
-
.create_upper_data_point(domain, x, y) ⇒ DataPoint
private
method to create the upper data point based on the given boundary.
-
.determine_coordinates(indices, delta_x, delta_y) ⇒ Object
private
singleton method to calculate the required coordinates for the requested data.
-
.get_boundary_points(x, y) ⇒ Hash
method to return the boundary point for a calculated interpolation.
-
.get_data_indices(x, y) ⇒ Hash
private
calculates the two nearest, lower indices for the given coordinates.
-
.get_index_to_next_lower_datapoint(data_domain, coordinate) ⇒ Numeric
private
singleton method to get the index to the next down rounded datapoint.
-
.get_upper_boundary(x, y) ⇒ Float
private
singleton method to serve the case that a boundary point os requested.
-
.set_attributes(meta_data, data_set) ⇒ Object
private
singleton method to set the attributes at the beginning of an interpolation.
Instance Attribute Details
#data_set ⇒ DataSet (readonly, private)
Returns the used data set.
44 45 46 |
# File 'lib/math/bilinear_interpolation.rb', line 44 def data_set @data_set end |
#meta_data ⇒ VisMetaData (readonly, private)
Returns the used meta data.
46 47 48 |
# File 'lib/math/bilinear_interpolation.rb', line 46 def @meta_data end |
Class Method Details
.apply_bilinear_interpolation(x, y) ⇒ Float (private)
singleton method to calculate the bilinear interpolation applies the formula:
(1-r)*(1-s)*d(x,y) + r*(1-s)*d(x+1,y) +
r*s*d(x+1,y+1) + (1-r)*s*d(x,y+1)
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/math/bilinear_interpolation.rb', line 90 def self.apply_bilinear_interpolation(x, y) return boundary_case(x,y) if check_for_upper_boundary(x, y) boundary = calculate_boundary_datapoints(x, y) # interpolate r = Interpolation::calculate_interpolation_factor(boundary[:d_xy], boundary[:d_x1y], x, y) s = Interpolation::calculate_interpolation_factor(boundary[:d_xy], boundary[:d_xy1], x, y) calculate_interpolation_result(1-r, 1-s, boundary[:d_xy].value) + calculate_interpolation_result(r, 1-s, boundary[:d_x1y].value) + calculate_interpolation_result(r, s, boundary[:d_x1y1].value) + calculate_interpolation_result(1-r, s, boundary[:d_xy1].value) end |
.bilinear_interpolation(meta_data, data_set, x, y) ⇒ Float
method for bilinear interpolation
25 26 27 28 29 30 |
# File 'lib/math/bilinear_interpolation.rb', line 25 def self.bilinear_interpolation(, data_set, x, y) set_attributes(, data_set) check_data_range(x, y) apply_bilinear_interpolation(x, y) end |
.boundary_case(x, y) ⇒ Float (private)
singleton method to apply the interpolation on a boundary case
203 204 205 206 207 208 209 210 211 |
# File 'lib/math/bilinear_interpolation.rb', line 203 def self.boundary_case(x, y) if (x == @meta_data.domain_x.upper && y == @meta_data.domain_y.upper) return get_upper_boundary(x,y) end return LinearInterpolation. linear_interpolation(create_data_point(0, 0, x, y), create_upper_data_point(@meta_data.domain_x, x, y), x, y) end |
.calculate_boundary_datapoints(x, y) ⇒ Hash (private)
singleton method to calculate the necessary boundary points
168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/math/bilinear_interpolation.rb', line 168 def self.calculate_boundary_datapoints(x, y) boundary = Hash.new() #getting boundary data points boundary[:d_xy] = create_data_point( 0, 0, x, y) boundary[:d_x1y] = create_data_point( 1, 0, x, y) boundary[:d_xy1] = create_data_point( 0, 1, x, y) boundary[:d_x1y1] = create_data_point(1, 1, x, y) return boundary end |
.calculate_interpolation_result(r, s, value) ⇒ Float (private)
singleton method to calculate the result of the bilinear interpolation
185 186 187 |
# File 'lib/math/bilinear_interpolation.rb', line 185 def self.calculate_interpolation_result(r, s, value) r * s * value end |
.check_data_range(x, y) ⇒ Object (private)
singleton method to check if the provided coordinates (x,y) lie within the data area specified by the meta information
64 65 66 67 68 69 70 |
# File 'lib/math/bilinear_interpolation.rb', line 64 def self.check_data_range(x, y) if ( !coordinate_in_dataset(@meta_data.domain_x, x) || !coordinate_in_dataset(@meta_data.domain_y, y)) raise RangeError, " Error: coordinate (#{x}, #{y}) does not lie" \ " in the data domain provided by meta_data.".red end end |
.check_for_upper_boundary(x, y) ⇒ Boolean (private)
singleton method to check if the provided coordinates lie on one of the upper dimension boundaries
194 195 196 197 |
# File 'lib/math/bilinear_interpolation.rb', line 194 def self.check_for_upper_boundary(x, y) return (x == @meta_data.domain_x.upper || y == @meta_data.domain_y.upper) end |
.coordinate_in_dataset(data_domain, coordinate) ⇒ Boolean (private)
singleton method to check if the provided coordinate lies within the given domain of the dataset
151 152 153 |
# File 'lib/math/bilinear_interpolation.rb', line 151 def self.coordinate_in_dataset(data_domain, coordinate) (coordinate <= data_domain.upper && coordinate >= data_domain.lower) end |
.create_data_point(delta_x, delta_y, x, y) ⇒ DataPoint (private)
creation of the boundary data points for the bilinear interpolation
116 117 118 119 120 121 122 123 124 125 |
# File 'lib/math/bilinear_interpolation.rb', line 116 def self.create_data_point(delta_x, delta_y, x, y) indices = get_data_indices(x, y) # with [x_index, y_index] coordinates = determine_coordinates(indices, delta_x, delta_y) begin data = @data_set.data[indices[:y] + delta_y][indices[:x] + delta_x] DataPoint.new(coordinates[:x], coordinates[:y], data) rescue StandardError DataPoint.new(coordinates[:x], coordinates[:y], nil) end end |
.create_upper_data_point(domain, x, y) ⇒ DataPoint (private)
method to create the upper data point based on the given boundary
218 219 220 221 222 223 224 |
# File 'lib/math/bilinear_interpolation.rb', line 218 def self.create_upper_data_point(domain, x, y) if (x == domain.upper) create_data_point(0, 1, x, y) # vertical case else create_data_point(1, 0, x, y) # horizontal case end end |
.determine_coordinates(indices, delta_x, delta_y) ⇒ Object (private)
singleton method to calculate the required coordinates for the requested data
134 135 136 137 138 139 140 141 142 143 |
# File 'lib/math/bilinear_interpolation.rb', line 134 def self.determine_coordinates(indices, delta_x, delta_y) coordinates = Hash.new() coordinates[:x] = (@meta_data.domain_x. get_coordinate_to_index(indices[:x])+ delta_x * @meta_data.domain_x.step).round(3) coordinates[:y] = (@meta_data.domain_y. get_coordinate_to_index(indices[:y])+ delta_y * @meta_data.domain_y.step).round(3) return coordinates end |
.get_boundary_points(x, y) ⇒ Hash
method to return the boundary point for a calculated interpolation
37 38 39 40 |
# File 'lib/math/bilinear_interpolation.rb', line 37 def self.get_boundary_points(x, y) check_data_range(x, y) calculate_boundary_datapoints(x, y) end |
.get_data_indices(x, y) ⇒ Hash (private)
calculates the two nearest, lower indices for the given coordinates
76 77 78 79 80 81 |
# File 'lib/math/bilinear_interpolation.rb', line 76 def self.get_data_indices(x, y) x_index = get_index_to_next_lower_datapoint(@meta_data.domain_x, x) y_index = get_index_to_next_lower_datapoint(@meta_data.domain_y, y) { :x => x_index, :y => y_index } end |
.get_index_to_next_lower_datapoint(data_domain, coordinate) ⇒ Numeric (private)
singleton method to get the index to the next down rounded datapoint
160 161 162 |
# File 'lib/math/bilinear_interpolation.rb', line 160 def self.get_index_to_next_lower_datapoint(data_domain, coordinate) ((coordinate - data_domain.lower) / data_domain.step).floor end |
.get_upper_boundary(x, y) ⇒ Float (private)
singleton method to serve the case that a boundary point os requested
230 231 232 233 |
# File 'lib/math/bilinear_interpolation.rb', line 230 def self.get_upper_boundary(x,y) indices = get_data_indices(x, y) @data_set.data[indices[:y]][indices[:x]] end |
.set_attributes(meta_data, data_set) ⇒ Object (private)
singleton method to set the attributes at the beginning of an interpolation
54 55 56 57 |
# File 'lib/math/bilinear_interpolation.rb', line 54 def self.set_attributes(, data_set) @data_set = data_set @meta_data = end |