Class: Motel::MovementStrategies::Elliptical

Inherits:
Motel::MovementStrategy show all
Defined in:
lib/motel/movement_strategies/elliptical.rb

Overview

The Elliptical MovementStrategy moves a location on an elliptical path described by major/minor axis direction vectors, and an eccentricity / semi_latus_rectum.

The path equation also depends on the value of the relative_to field indicating if the parent location is the center or a foci of the ellipse. Lastly a speed value is required indicating the angular velocity of the location.

To be valid you must specify eccentricity, semi_latus_rectum, and speed at a minimum

Constant Summary collapse

CENTER =

Indicates that parent location is at center of elliptical path

"center"
FOCI =

Indicates that parent location is at one of the focis of the elliptical path

"foci"

Instance Attribute Summary collapse

Attributes inherited from Motel::MovementStrategy

#step_delay

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Motel::MovementStrategy

#change?, json_create

Constructor Details

#initialize(args = {}) ⇒ Elliptical

Motel::MovementStrategies::Elliptical initializer

Direction vectors will be normalized if not already

Options Hash (args):

  • :direction (Array<Float>)

    array containing x,y,z coords of major and minor direction vectors

  • :dmajx (Float)

    x coordinate of major direction vector

  • :dmajy (Float)

    y coordinate of major direction vector

  • :dmajz (Float)

    z coordinate of major direction vector

  • :dminx (Float)

    x coordinate of minor direction vector

  • :dminy (Float)

    y coordinate of minor direction vector

  • :dminz (Float)

    z coordinate of minor direction vector

  • :speed (Float)

    speed to assign to movement strategy

  • :relative_to (CENTER, FOCI)

    how the parent location is related to this elliptical path

  • :e (Float)

    eccentricity to assign to elliptical path

  • :p (Float)

    semi latus rectum to assign to elliptical path

Raises:


93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/motel/movement_strategies/elliptical.rb', line 93

def initialize(args = {})
   @dmajx, @dmajy, @dmajz, @dminx, @dminy, @dminz =
     (args[:direction] || args['direction'] || [1,0,0,0,1,0]).flatten

   dmaj = args[:dmaj] || args['dmaj'] || [@dmajx,@dmajy,@dmajz]
   dmin = args[:dmin] || args['dmin'] || [@dminx,@dminy,@dminz]
   @dmajx, @dmajy, @dmajz = dmaj
   @dminx, @dminy, @dminz = dmin

  attr_from_args args,
    :relative_to  => CENTER,
    :speed => nil, :e => nil, :p => nil,
    :dmajx =>   @dmajx, :dmajy =>   @dmajy, :dmajz =>   @dmajz,
    :dminx =>   @dminx, :dminy =>   @dminy, :dminz =>   @dminz

  super(args)

  @dmajx, @dmajy, @dmajz = Motel::normalize(@dmajx, @dmajy, @dmajz)
  @dminx, @dminy, @dminz = Motel::normalize(@dminx, @dminy, @dminz)
end

Instance Attribute Details

#dmajxObject

Direction vector corresponding to the major axis of the elliptical path


56
57
58
# File 'lib/motel/movement_strategies/elliptical.rb', line 56

def dmajx
  @dmajx
end

#dmajyObject

Direction vector corresponding to the major axis of the elliptical path


56
57
58
# File 'lib/motel/movement_strategies/elliptical.rb', line 56

def dmajy
  @dmajy
end

#dmajzObject

Direction vector corresponding to the major axis of the elliptical path


56
57
58
# File 'lib/motel/movement_strategies/elliptical.rb', line 56

def dmajz
  @dmajz
end

#dminxObject

Direction vector corresponding to the minor axis of the elliptical path


64
65
66
# File 'lib/motel/movement_strategies/elliptical.rb', line 64

def dminx
  @dminx
end

#dminyObject

Direction vector corresponding to the minor axis of the elliptical path


64
65
66
# File 'lib/motel/movement_strategies/elliptical.rb', line 64

def dminy
  @dminy
end

#dminzObject

Direction vector corresponding to the minor axis of the elliptical path


64
65
66
# File 'lib/motel/movement_strategies/elliptical.rb', line 64

def dminz
  @dminz
end

#eObject Also known as: eccentricity

Describes the elliptical path through which the location moves


49
50
51
# File 'lib/motel/movement_strategies/elliptical.rb', line 49

def e
  @e
end

#pObject Also known as: semi_latus_rectum

Describes the elliptical path through which the location moves


49
50
51
# File 'lib/motel/movement_strategies/elliptical.rb', line 49

def p
  @p
end

#relative_toObject

CENTER, FOCI

value indicates if the parent

of the location tracked by this strategy is at the center or the foci
of the ellipse.

Affects how elliptical path is calculated


43
44
45
# File 'lib/motel/movement_strategies/elliptical.rb', line 43

def relative_to
  @relative_to
end

#speedObject

Distance the location moves per second


46
47
48
# File 'lib/motel/movement_strategies/elliptical.rb', line 46

def speed
  @speed
end

Class Method Details

.random(args = {}) ⇒ Object

Generate and return a random elliptical movement strategy


351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'lib/motel/movement_strategies/elliptical.rb', line 351

def self.random(args = {})
  dimensions  = args[:dimensions]  || 3
  relative_to = args[:relative_to] || CENTER

  min_e = min_p = min_s = 0
  min_e = args[:min_e] if args.has_key?(:min_e)
  min_p = args[:min_p] if args.has_key?(:min_p)
  min_s = args[:min_s] if args.has_key?(:min_s)

  max_e = max_p = max_s = nil
  max_e = args[:max_e] if args.has_key?(:max_e)
  max_p = args[:max_p] if args.has_key?(:max_p)
  max_s = args[:max_s] if args.has_key?(:max_s)

  eccentricity      = min_e + (max_e.nil? ? rand : rand((max_e - min_e)*10000)/10000)
  speed             = min_s + (max_s.nil? ? rand : rand((max_s - min_s)*10000)/10000)
  semi_latus_rectum = min_p + (max_p.nil? ? rand : rand((max_p - min_p)))

  direction = args[:direction] || Motel::random_axis(:dimensions => dimensions)
  dmajx, dmajy, dmajz = *direction[0]
  dminx, dminy, dminz = *direction[1]

  Elliptical.new :relative_to => relative_to, :speed => speed,
                 :e => eccentricity, :p => semi_latus_rectum,
                 :dmajx => dmajx, :dmajy => dmajy, :dmajz => dmajz,
                 :dminx => dminx, :dminy => dminy, :dminz => dminz
end

Instance Method Details

#directionObject

Combined direction vector


72
73
74
# File 'lib/motel/movement_strategies/elliptical.rb', line 72

def direction
  dmaj + dmin
end

#dmajObject

Combined major direction vector


59
60
61
# File 'lib/motel/movement_strategies/elliptical.rb', line 59

def dmaj
  [@dmajx, @dmajy, @dmajz]
end

#dminObject

Combined minor direction vector


67
68
69
# File 'lib/motel/movement_strategies/elliptical.rb', line 67

def dmin
  [@dminx, @dminy, @dminz]
end

#location_valid?(location) ⇒ Boolean Also known as: intersects?

Return boolean indicating if the given location is on the ellipse or not TODO replace w/ intersects (below) ?


331
332
333
334
335
336
337
338
# File 'lib/motel/movement_strategies/elliptical.rb', line 331

def location_valid?(location)
   x,y,z = closest_coordinates(location)

   return false if x.nil? || y.nil? || z.nil?
   return (x - location.x).round_to(4) == 0 &&
          (y - location.y).round_to(4) == 0 &&
          (z - location.z).round_to(4) == 0
end

#move(loc, elapsed_seconds) ⇒ Object

Implementation of Motel::MovementStrategy#move


137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/motel/movement_strategies/elliptical.rb', line 137

def move(loc, elapsed_seconds)
  # make sure this movement strategy is valid
  unless valid?
     ::RJR::Logger.warn "elliptical movement strategy not valid, not proceeding with move"
     return
  end

  # make sure location is on ellipse
  unless location_valid? loc
     cx,cy,cz = closest_coordinates loc
     ::RJR::Logger.warn "location #{loc} not on ellipse, adjusting to closest location #{cx},#{cy},#{cz} before moving"
     # FIXME raise error if cx,cy,cz is nil
     loc.x,loc.y,loc.z = cx,cy,cz
  end

  ::RJR::Logger.debug "moving location #{loc.id} via elliptical movement strategy"

  # calculate distance moved and update x,y,z accordingly
  distance = speed * elapsed_seconds

  nX,nY,nZ = coordinates_from_theta(theta(loc) + distance)
  loc.x = nX
  loc.y = nY
  loc.z = nZ
end

#random_coordinatesObject


341
342
343
# File 'lib/motel/movement_strategies/elliptical.rb', line 341

def random_coordinates
  coordinates_from_theta(Math.random * 2 * Math::PI)
end

#to_json(*a) ⇒ Object

Convert movement strategy to json representation and return it


164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/motel/movement_strategies/elliptical.rb', line 164

def to_json(*a)
  { 'json_class' => self.class.name,
    'data'       => { :step_delay   => step_delay,
                      :speed        => speed,
                      :relative_to  => relative_to,
                      :e => e,
                      :p => p,
                      :dmajx => dmajx,
                      :dmajy => dmajy,
                      :dmajz => dmajz,
                      :dminx => dminx,
                      :dminy => dminy,
                      :dminz => dminz }
  }.to_json(*a)
end

#to_sObject

Convert movement strategy to human readable string and return it


181
182
183
# File 'lib/motel/movement_strategies/elliptical.rb', line 181

def to_s
  "elliptical-(rt_#{relative_to}/s#{speed}/e#{e}/p#{p}/d#{direction})"
end

#valid?Boolean

Return boolean indicating if this movement strategy is valid

Tests the various attributes of the elliptical movement strategy, returning 'true' if everything is consistent, else false.

Currently tests

  • direction vectors are normalized

  • direction vectors are orthogonal

  • eccentricity is a valid numeric > 0

  • semi latus rectum is a valid numeric > 0

  • speed is a valid numeric > 0

  • relative_to is CENTER or FOCI


126
127
128
129
130
131
132
133
134
# File 'lib/motel/movement_strategies/elliptical.rb', line 126

def valid?
  Motel::normalized?(@dmajx, @dmajy, @dmajz) &&
  Motel::normalized?(@dminx, @dminy, @dminz) &&
  Motel::orthogonal?(@dmajx, @dmajy, @dmajz, @dminx, @dminy, @dminz) &&
  @e.numeric? && @e >= 0 && @e <= 1 &&
  @p.numeric? && @p > 0 &&
  @speed.numeric? && @speed > 0 &&
  [CENTER, FOCI].include?(@relative_to)
end