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.



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

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.



6
7
8
# File 'lib/mittsu/math/spline.rb', line 6

def points
  @points
end

Instance Method Details

#control_points_arrayObject



45
46
47
48
49
# 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) ⇒ Object



14
15
16
17
18
# 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) ⇒ Object



51
52
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
# 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) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 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) ⇒ Object



87
88
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
# 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