class Mittsu::Spline

Constants

Length
Point

Attributes

points[RW]

Public Class Methods

new(points) click to toggle source
# File lib/mittsu/math/spline.rb, line 8
def initialize(points)
  @points = points
  @c = []
  @v3 = Point.new(0.0, 0.0, 0.0)
end

Public Instance Methods

control_points_array() click to toggle source
# File lib/mittsu/math/spline.rb, line 45
def control_points_array
  @points.map do |p|
    [ p.x, p.y, p.z ]
  end
end
init_from_array(a) click to toggle source
# File lib/mittsu/math/spline.rb, line 14
def init_from_array(a)
  @points = a.map do |p|
    Point.new(*p.take(3))
  end
end
length(n_sub_divisions = 100) click to toggle source
# File lib/mittsu/math/spline.rb, line 51
def length(n_sub_divisions = 100)
  point, int_point, old_int_point = 0, 0, 0
  old_position = Mittsu::Vector3.new
  tmp_vec = Mittsu::Vector3.new
  chunk_lengths = []
  total_length = 0

  # first point has 0 length
  chunk_lengths << 0
  n_samples = @points.length * n_sub_divisions
  old_position.copy(@points.first)

  (1...n_samples).each do |i|
    index = i.to_f / n_samples.to_f

    position = self.point(index)
    tmp_vec.copy(position)

    total_length += tmp_vec.distance_to(old_position)

    old_position.copy(position)

    point = (@points.length - 1) * index
    int_point = point.floor

    if (int_point != old_int_point)
      chunk_lengths[int_point] = total_length
      old_int_point = int_point
    end
  end

  # last point ends with total length
  chunk_lengths << total_length
  Length.new(chunk_lengths, total_length)
end
point(k) click to toggle source
# File lib/mittsu/math/spline.rb, line 20
def point(k)
  point = (@points.length - 1) * k
  int_point = point.floor
  weight = point - int_point

  @c[0] = int_point.zero? ? int_point : int_point - 1
  @c[1] = int_point
  @c[2] = int_point > @points.length - 1 ? @points.length - 1 : int_point + 1
  @c[3] = int_point > @points.length - 3 ? @points.length - 1 : int_point + 2

  pa = @points[c[0]]
  pb = @points[c[1]]
  pc = @points[c[2]]
  pd = @points[c[3]]

  w2 = weight * weight
  w3 = weight * w2

  v3.x = interpolate(pa.x, pb.x, pc.x, pd.x, weight, w2, w3)
  v3.y = interpolate(pa.y, pb.y, pc.y, pd.y, weight, w2, w3)
  v3.z = interpolate(pa.z, pb.z, pc.z, pd.z, weight, w2, w3)

  v3
end
reparametrize_by_arc_length(sampling_coef) click to toggle source
# File lib/mittsu/math/spline.rb, line 87
def reparametrize_by_arc_length(sampling_coef)
  new_points = []
  tmp_vec = Mittsu::Vector3.new
  sl = self.length

  new_points << tmp_vec.copy(@points[0]).clone

  @points.each_with_index do |p,i|
    #tmp_vec.copy(@points[i-1])
    #linear_distance = tmp_vec.distance_to(p)

    real_distance = sl.chunks[i] - sl.chunks[i - 1]

    sampling = (sampling_coef * real_distance / sl.total).ceil

    index_current = (i.to_f - 1.0) / (@points.length.to_f - 1.0)
    index_next = i.to_f / (@points.length.to_f - 1.0)

    (1...sampling-1).each do |j|
      index = index_current + j * (1.0 / sampling) * (index_next - index_current)

      position = self.point(index)
      new_points << tmp_vec.copy(position).clone
    end

    new_points << tmp_vec.copy(p).clone
  end
  @points = new_points
end

Private Instance Methods

interpolate(p0, p1, p2, p3, t, t2, t3) click to toggle source
# File lib/mittsu/math/spline.rb, line 119
def interpolate(p0, p1, p2, p3, t, t2, t3)
  v0 = (p2 - p0) * 0.5
  v1 = (p4 - p1) * 0.5

  (2.0 * (p1 - p2) + v0 + v1) * t3 + (-3.0 * (p1 - p2) - 2.0 * v0 - v1) * t2 + v0 * t + p1?
end