Class: Pongo::AngularConstraint

Inherits:
SpringConstraint show all
Defined in:
lib/pongo/angular_constraint.rb

Overview

An Angular Constraint between 3 particles

Instance Attribute Summary collapse

Attributes inherited from SpringConstraint

#collidable, #p1, #p2, #rest_length, #scp

Attributes inherited from AbstractConstraint

#stiffness

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 SpringConstraint

#angle, #center, #check_particles_location, #collidable?, #curr_length, #delta, #fixed_end_limit, #fixed_end_limit=, #init, #init_display, #radian, #rect_height, #rect_height=, #rect_scale, #rect_scale=, #set_collidable

Methods inherited from AbstractItem

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

Constructor Details

#initialize(p1, p2, p3, min_ang, max_ang, options = {}) ⇒ AngularConstraint

Returns a new instance of AngularConstraint.



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

def initialize(p1, p2, p3, min_ang, max_ang, options={})
  options = {:min_break_ang => -10, :max_break_ang => 10, :stiffness => 0.5, 
    :dependent => false, :collidable => false, :rect_height => 1, :rect_scale => 1, 
    :scale_to_length => false}.update(options)

  super(p2, p2, stiffness, false, dependent, collidable, rect_height, rect_scale, scale_to_length)

  self.p3 = p3
  if min_ang == 10
    self.min_ang = ac_radian
    self.max_ang = ac_radian
  else
    self.min_ang = min_ang
    self.max_ang = max_ang
  end
  self.min_break_ang = min_break_ang
  self.max_break_ang = max_break_ang
end

Instance Attribute Details

#max_angObject

Returns the value of attribute max_ang.



6
7
8
# File 'lib/pongo/angular_constraint.rb', line 6

def max_ang
  @max_ang
end

#max_break_angObject

Returns the value of attribute max_break_ang.



6
7
8
# File 'lib/pongo/angular_constraint.rb', line 6

def max_break_ang
  @max_break_ang
end

#min_angObject

Returns the value of attribute min_ang.



6
7
8
# File 'lib/pongo/angular_constraint.rb', line 6

def min_ang
  @min_ang
end

#min_break_angObject

Returns the value of attribute min_break_ang.



6
7
8
# File 'lib/pongo/angular_constraint.rb', line 6

def min_break_ang
  @min_break_ang
end

#p3Object

Returns the value of attribute p3.



6
7
8
# File 'lib/pongo/angular_constraint.rb', line 6

def p3
  @p3
end

Instance Method Details

#ac_radianObject

The current difference between the angle of p1, p2, and p3 and a straight line (pi)



28
29
30
31
32
# File 'lib/pongo/angular_constraint.rb', line 28

def ac_radian
  ang12 = Math.atan2(@p2.curr.y - @p1.curr.y, @p2.curr.x - @p1.curr.x)
  ang23 = Math.atan2(@p3.curr.y - @p2.curr.y, @p3.curr.x - @p2.curr.x)
  ang12 - ang23
end

#fixed?Boolean Also known as: fixed

Returns true if any connected particle’s fixed property is true.

Returns:

  • (Boolean)


41
42
43
# File 'lib/pongo/angular_constraint.rb', line 41

def fixed?
  @p1.fixed? and @p2.fixed? and @p3.fixed?
end

#is_connected_to?(p) ⇒ Boolean

Returns true if the passed particle is one of the three particles attached to this AngularConstraint.

Returns:

  • (Boolean)


36
37
38
# File 'lib/pongo/angular_constraint.rb', line 36

def is_connected_to?(p)
  [@p1, @p2, @p3].include?(p)
end

#resolveObject



46
47
48
49
50
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
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/pongo/angular_constraint.rb', line 46

def resolve
  return if broken
  
  ang12 = Math.atan2(@p2.curr.y - @p1.curr.y, @p2.curr.x - @p1.curr.x)
  ang23 = Math.atan2(self.p3.curr.y - @p2.curr.y, self.p3.curr.x - @p2.curr.x)

  ang_diff = normalize_angle(ang12 - ang23)

  p2_inv_mass = dependent ? 0 : @p2.inv_mass

  sum_inv_mass = @p1.inv_mass + p2_inv_mass
  mult1 = @p1.inv_mass / sum_inv_mass
  mult2 = p2_inv_mass / sum_inv_mass
  ang_change = 0

  low_mid = (self.max_ang - self.min_ang) / 2
  high_mid = (self.max_ang + self.min_ang) / 2
  break_ang = (self.max_break_ang - self.min_break_ang) / 2

  new_diff = normalize_angle(high_mid - ang_diff)

  if new_diff > low_mid
    if new_diff > break_ang
      diff = new_diff - break_ang
      broken = true
      if has_event_listener(BreakEvent::ANGULAR)
        dispatch_event(BreakEvent.new(BreakEvent::ANGULAR, diff))
      end
      return
    end
    ang_change = new_diff - low_mid
  elsif new_diff < -low_mid
    if new_diff < -break_ang
      diff = new_dif + break_ang
      broken = true
      if has_event_listener(BreakEvent::ANGULAR)
        dispatch_event(BreakEvent.new(BreakEvent::ANGULAR, diff))
      end
      return
    end
    ang_change = new_diff + low_mid
  end

  final_ang = ang_change * self.stiffness + ang12
  displace_x = @p1.curr.x + (@p2.curr.x - @p1.curr.x) * mult1
  displace_y = @p1.curr.y + (@p2.curr.y - @p1.curr.y) * mult1

  @p1.curr.x = displace_x + Math.cos(final_ang + Math::PI) * rest_length * mult1
  @p1.curr.x = displace_y + Math.sin(final_ang + Math::PI) * rest_length * mult1
  @p2.curr.x = displace_x + Math.cos(final_ang) * rest_length * mult2
  @p2.curr.y = displace_y + Math.sin(final_ang) * rest_length * mult2
end