Class: Mittsu::Spline

Inherits:
Object
  • Object
show all
Defined in:
lib/mittsu/math/spline.rb

Defined Under Namespace

Classes: Length, Point

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(points) ⇒ Spline

Returns a new instance of Spline.



10
11
12
13
14
# File 'lib/mittsu/math/spline.rb', line 10

def initialize(points)
  @points = points
  @c = []
  @v3 = Point.new(0.0, 0.0, 0.0)
end

Instance Attribute Details

#pointsObject

Returns the value of attribute points.



8
9
10
# File 'lib/mittsu/math/spline.rb', line 8

def points
  @points
end

Instance Method Details

#control_points_arrayObject



47
48
49
50
51
# File 'lib/mittsu/math/spline.rb', line 47

def control_points_array
  @points.map do |p|
    [ p.x, p.y, p.z ]
  end
end

#init_from_array(a) ⇒ Object



16
17
18
19
20
# File 'lib/mittsu/math/spline.rb', line 16

def init_from_array(a)
  @points = a.map do |p|
    Point.new(*p.take(3))
  end
end

#length(n_sub_divisions = 100) ⇒ Object



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
82
83
84
85
86
87
# File 'lib/mittsu/math/spline.rb', line 53

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) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/mittsu/math/spline.rb', line 22

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) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/mittsu/math/spline.rb', line 89

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