Class: Pongo::SpringConstraintParticle

Inherits:
RectangleParticle show all
Defined in:
lib/pongo/spring_constraint_particle.rb

Instance Attribute Summary collapse

Attributes inherited from RectangleParticle

#axes, #extents, #radian

Attributes inherited from AbstractParticle

#center, #collidable, #collision, #curr, #first_collision, #force_list, #forces, #interval, #kfr, #multisample, #prev, #samp, #temp

Attributes inherited from AbstractItem

#always_repaint, #display_object, #display_object_offset, #display_object_rotation, #fill_alpha, #fill_color, #line_alpha, #line_color, #line_thickness, #renderer, #solid, #user_data, #visible

Instance Method Summary collapse

Methods inherited from RectangleParticle

#angle, #angle=, #height, #height=, #projection, #set_axes, #width, #width=

Methods inherited from AbstractParticle

#accumulate_forces, #add_force, #clear_forces, #collidable!, #collidable?, #components, #elasticity=, #position, #position=, #px, #px=, #py, #py=, #reset_first_collision!, #solid?, #test_particle_events, #update, #velocity=

Methods inherited from AbstractItem

#add_event_listener, #always_redraw!, #always_redraw=, #always_redraw?, #cleanup, #dispatch_event, #has_event_listener, #set_fill, #set_line, #set_style, #visible!, #visible?

Constructor Details

#initialize(p1, p2, p, rect_height, rect_scale, scale_to_length) ⇒ SpringConstraintParticle

Returns a new instance of SpringConstraintParticle.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/pongo/spring_constraint_particle.rb', line 10

def initialize(p1, p2, p, rect_height, rect_scale, scale_to_length)
  super(0.0, 0.0, 0.0, 0.0, :fixed => false)

  @p1 = p1
  @p2 = p2

  self.lamda = Vector.new
  self.avg_velocity = Vector.new

  @parent = p
  @rect_scale = rect_scale
  @rect_height = rect_height
  @scale_to_length = scale_to_length

  @fixed_end_limit = 0.0
  @rca = Vector.new
  @rcb = Vector.new
end

Instance Attribute Details

#avg_velocityObject

Returns the value of attribute avg_velocity.



8
9
10
# File 'lib/pongo/spring_constraint_particle.rb', line 8

def avg_velocity
  @avg_velocity
end

#fixed_end_limitObject

Returns the value of attribute fixed_end_limit.



8
9
10
# File 'lib/pongo/spring_constraint_particle.rb', line 8

def fixed_end_limit
  @fixed_end_limit
end

#lamdaObject

Returns the value of attribute lamda.



8
9
10
# File 'lib/pongo/spring_constraint_particle.rb', line 8

def lamda
  @lamda
end

#p1Object

Returns the value of attribute p1.



8
9
10
# File 'lib/pongo/spring_constraint_particle.rb', line 8

def p1
  @p1
end

#p2Object

Returns the value of attribute p2.



8
9
10
# File 'lib/pongo/spring_constraint_particle.rb', line 8

def p2
  @p2
end

#parentObject

Returns the value of attribute parent.



8
9
10
# File 'lib/pongo/spring_constraint_particle.rb', line 8

def parent
  @parent
end

#rcaObject

Returns the value of attribute rca.



8
9
10
# File 'lib/pongo/spring_constraint_particle.rb', line 8

def rca
  @rca
end

#rcbObject

Returns the value of attribute rcb.



8
9
10
# File 'lib/pongo/spring_constraint_particle.rb', line 8

def rcb
  @rcb
end

#rect_heightObject

Returns the value of attribute rect_height.



8
9
10
# File 'lib/pongo/spring_constraint_particle.rb', line 8

def rect_height
  @rect_height
end

#rect_scaleObject

Returns the value of attribute rect_scale.



8
9
10
# File 'lib/pongo/spring_constraint_particle.rb', line 8

def rect_scale
  @rect_scale
end

#sObject

Returns the value of attribute s.



8
9
10
# File 'lib/pongo/spring_constraint_particle.rb', line 8

def s
  @s
end

#scale_to_lengthObject

Returns the value of attribute scale_to_length.



8
9
10
# File 'lib/pongo/spring_constraint_particle.rb', line 8

def scale_to_length
  @scale_to_length
end

Instance Method Details

#closest_param_point(c) ⇒ Object

given point c, returns a parameterized location on this SCP. Note this is just treating the SCP as if it were a line segment (ab).



127
128
129
130
131
# File 'lib/pongo/spring_constraint_particle.rb', line 127

def closest_param_point(c)
  ab = @p2.curr - @p1.curr
  t = (ab.dot(c - @p1.curr)) / (ab.dot(ab))
  MathUtil.clamp(t, 0.0, 1.0)
end

#closest_pt_segment_segmentObject

pp1-pq1 will be the SCP line segment on which we need parameterized s.



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/pongo/spring_constraint_particle.rb', line 204

def closest_pt_segment_segment
  pp1 = @p1.curr
  pq1 = @p2.curr
  pp2 = @rca
  pq2 = @rcb

  d1 = pq1 - pp1
  d2 = pq2 - pp2
  r = pp1 - pp2

  a = d1.dot(d1)
  e = d2.dot(d2)
  f = d2.dot(r)

  c = d1.dot(r)
  b = d1.dot(d2)
  denom = a * e - b * b

  s = denom != 0.0 ? MathUtil.clamp((b * f - c * e) / denom, 0.0, 1.0) : 0.5
  t = (b * s + f) / e

  t, s = t < 0 \
    ? [0.0, MathUtil.clamp(-c / a, 0.0, 1.0)] \
    : [1.0, MathUtil.clamp((b - c) / a, 0.0, 1.0)]

  c1 = pp1 + (d1 * s)
  c2 = pp2 + (d2 * t)
  c1mc2 = c1 - c2
  c1mc2.dot(c1mc2)
end

#drawObject



51
52
53
# File 'lib/pongo/spring_constraint_particle.rb', line 51

def draw
  #throw NotImplementedError
end

#elasticityObject



33
34
35
# File 'lib/pongo/spring_constraint_particle.rb', line 33

def elasticity
  (@p1.elasticity * @p2.elasticity) / 2.0
end

#fixed?Boolean Also known as: fixed

Returns:

  • (Boolean)


67
68
69
# File 'lib/pongo/spring_constraint_particle.rb', line 67

def fixed?
  @parent.fixed?
end

#frictionObject



37
38
39
# File 'lib/pongo/spring_constraint_particle.rb', line 37

def friction
  (@p1.friction * @p2.friction) / 2.0
end

#get_contact_point_param(p) ⇒ Object Also known as: contact_point_param

returns a contact location on this SCP expressed as a parametric value in [0,1]



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/pongo/spring_constraint_particle.rb', line 134

def get_contact_point_param(p)
  if p.is_a?(CircleParticle)
    closest_param_point(p.curr)
  elsif p.is_a?(RectangleParticle)
    # go through the sides of the colliding rectangle as line segments
    shortest_index = 0
    params_list = []
    shortest_distance = Numeric::POSITIVE_INFINITY
    4.times do |i|
      set_corners(p, i)

      # check for closest points on SCP to side of rectangle
      d = closest_pt_segment_segment
      if d < shortest_distance
        shortest_distance = d
        shortest_index = i
        params_list[i] = @s
      end
      params_list[shortest_index]
    end
  end
end

#initObject



47
48
49
# File 'lib/pongo/spring_constraint_particle.rb', line 47

def init
  #throw NotImplementedError
end

#init_displayObject



55
56
57
# File 'lib/pongo/spring_constraint_particle.rb', line 55

def init_display
  #throw NotImplementedError
end

#inv_massObject



59
60
61
62
63
64
65
# File 'lib/pongo/spring_constraint_particle.rb', line 59

def inv_mass
  if @p1.fixed? and @p2.fixed?
    0
  else
    1.0 / self.mass
  end
end

#massObject



29
30
31
# File 'lib/pongo/spring_constraint_particle.rb', line 29

def mass
  (@p1.mass * @p2.mass) / 2.0
end

#resolve_collision(mtd, vel, n, d, o, p) ⇒ Object



82
83
84
85
86
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
116
117
118
119
120
121
122
123
# File 'lib/pongo/spring_constraint_particle.rb', line 82

def resolve_collision(mtd, vel, n, d, o, p)
  test_particle_events(p)
  return if fixed? or not p.solid?

  t = contact_point_param(p)
  c1 = 1 -t
  c2 = t

  # if one is fixed then move the other particle the entire way out of 
  # collision. also, dispose of collisions at the sides of the scp. The higher
  # the fixedEndLimit value, the more of the scp not be effected by collision. 
  if @p1.fixed?
    return if c2 <= @fixed_end_limit
    lamda.set_to(mtd.x / c2, mtd.y / c2)
    @p2.curr.plus!(lamda)
    @p2.velocity = vel
  elsif @p2.fixed?
    return if c1 <= @fixed_end_limit
    lamda.set_to(mtd.x / c1, mtd.y / c1)
    @p1.curr.plus!(lamda)
    @p1.velocity = vel
  else
    # else both non fixed - move proportionally out of collision
    denom = c1 * c1 + c2 * c2
    return if denom == 0
    lamda.set_to(mtd.x / denom, mtd.y / denom)

    @p1.curr.plus!(lamda * c1)
    @p2.curr.plus!(lamda * c2)
    
    if t == 0.5
      # if collision is in the middle of SCP set the velocity of both end 
      # particles
      @p1.velocity = vel
      @p2.velocity = vel
    else
      # otherwise change the velocity of the particle closest to contact
      corr_particle = t < 0.5 ? @p1 : @p2
      corr_particle.velocity = vel
    end
  end
end

#set_corners(r, i) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/pongo/spring_constraint_particle.rb', line 158

def set_corners(r, i)
  rx = r.curr.x
  ry = r.curr.y

  axes = r.axes
  extents = r.extents

  ae0_x = axes[0].x * extents[0]
  ae0_y = axes[0].y * extents[0]
  ae1_x = axes[1].x * extents[1]
  ae1_y = axes[1].y * extents[1]

  emx = ae0_x - ae1_x
  emy = ae0_y - ae1_y
  epx = ae0_x + ae1_x
  epy = ae0_y + ae1_y

  case i
  when 0
    # 0 and 1
    @rca.x = rx - epx;
    @rca.y = ry - epy;
    @rcb.x = rx + emx;
    @rcb.y = ry + emy;
  when 1
    # 1 and 2
    @rca.x = rx + emx;
    @rca.y = ry + emy;
    @rcb.x = rx + epx;
    @rcb.y = ry + epy;
  when 2
    # 2 and 3
    @rca.x = rx + epx;
    @rca.y = ry + epy;
    @rcb.x = rx - emx;
    @rcb.y = ry - emy;
  when 3
    # 3 and 0
    @rca.x = rx - emx;
    @rca.y = ry - emy;
    @rcb.x = rx - epx;
    @rcb.y = ry - epy;
  end
end

#update_positionObject

called only on collision



73
74
75
76
77
78
79
80
# File 'lib/pongo/spring_constraint_particle.rb', line 73

def update_position
  @curr.set_to(@parent.center)
  self.width = @scale_to_length \
    ? @parent.curr_length * @rect_scale \
    : @parent.rest_length * @rect_scale
  self.height = @rect_height
  self.radian = @parent.radian
end

#velocityObject



41
42
43
44
45
# File 'lib/pongo/spring_constraint_particle.rb', line 41

def velocity
  p1v = @p1.velocity
  p2v = @p2.velocity
  @avg_velocity.set_to((p1v.x + p2v.x) / 2.0, (p1v.y + p2v.y) / 2.0)
end