lib/interpolation.rb in xrvg-0.0.2 vs lib/interpolation.rb in xrvg-0.0.3

- old
+ new

@@ -1,10 +1,11 @@ # Interpolation file. # # See # - +Interpolation+ # - +Interpolator+ +# - +InterpolatorQuad+ require 'utils' require 'attributable' # Interpolation module @@ -31,23 +32,23 @@ # from an input between 0.0 and 1.0, returns linear interpolated value # # interpolate uses + and * scalar operators on interpolation values def interpolate( dindex ) result = nil - pvalue, pindex = self.samplelist[0..1] - self.samplelist.foreach do |value, index| + pindex, pvalue = self.samplelist[0..1] + self.samplelist.foreach do |index, value| if dindex <= index if dindex == index return value end result = pvalue + ((value + pvalue * (-1.0) ) * ((dindex - pindex) / (index - pindex ))) break end pvalue, pindex = value, index end if not result - result = self.samplelist[-2] + result = self.samplelist[-1] end return result end end @@ -56,6 +57,102 @@ # Simply instanciated module in a class class Interpolator include Attributable attribute :samplelist include Interpolation +end + +class QuadRange + + def initialize( limit, quadleft, quadright, range=nil ) + @limit = limit + @quadleft = quadleft + @quadright = quadright + @range = range + end + + def limit + return @limit + end + + def range( index ) + if @limit + if index < @limit + return @quadleft.range( index ) + else + return @quadright.range( index ) + end + else + return @range + end + end +end + +# QuadTree class +# = Intro +# Optim class to look for predefine ranges for a value. Is actually a binary tree data structure, but used as unlinear space partitioner. +# = Example +# quad = QuadTree.new( [0.0,1.0, 0.2,0.0, 0.6,1.0, 0.8,0.0, 1.0,1.0] ) +# quad.range( 0.5 ); #=> [0.2,0.0,0.6,1.0] +class QuadTree + + def initialize( samplelist ) #:nodoc: + quads = [] + ends = [] + samplelist.foreach(2).pairs do |ppair, pair| + pindex, pvalue = ppair + index, value = pair + quads << QuadRange.new( nil, nil, nil, [pindex, pvalue, index, value] ) + ends << index + end + @root = build_quads( quads, ends ) + end + + def build_quads( quads, ends ) #:nodoc: + newquads = [] + newends = [] + index = 0 + quads.foreach do |quad1, quad2| + newquads << QuadRange.new( ends[2*index], quad1, quad2, nil) + newends << ends[2*index + 1] + index += 1 + end + if newquads.size == 1 + return newquads[0] + else + return build_quads( newquads, newends ) + end + end + + # utilitary method to retrieve range of index + # QuadTree.new( [0.0,1.0, 0.2,0.0, 0.6,1.0, 0.8,0.0, 1.0,1.0] ).range( 0.5 ); #=> [0.2,0.0,0.6,1.0] + def range( index ) + return @root.range( index ) + end +end + +# Quad tree interpolator +# +# Use QuadTree to retrieve range of values between linear interpolation. +# +# Used in BezierSpline to compute parameter from length. +class InterpolatorQuad < Interpolator + + def compute_quad #:nodoc: + @quad = QuadTree.new( self.samplelist ) + end + + # - first use QuadTree range to retrieve range of dindex, + # - then linearly interpolate + def interpolate( dindex ) + if not @quad + compute_quad + end + pindex, pvalue, index, value = @quad.range( dindex ) + if pindex.fequal?(index) + result = value + else + result = pvalue + ((value + pvalue * (-1.0) ) * ((dindex - pindex) / (index - pindex ))) + end + return result + end end