Module: Sc2::Position
- Included in:
- Api::Point, Api::Point2D, Api::PointI, Api::PowerSourceExtension, Api::Size2DI
- Defined in:
- lib/sc2ai/protocol/extensions/position.rb
Overview
A unified construct that tames Api::* messages which contain location data Items which are of type Sc2::Position will have #x and #y property at the least.
Constant Summary collapse
- TOLERANCE =
Tolerance for floating-point comparisons.
1e-9
Instance Method Summary collapse
-
#==(other) ⇒ Object
Loose equality matches on floats x and y.
-
#add(other) ⇒ Api::Point2D
(also: #+)
A new point representing the sum of this point and the other point.
-
#angle_to(other) ⇒ Float
The angle between this vector and the other vector, in radians.
-
#away_from(other, distance) ⇒ Api::Point2D
Moves in direction away from the other point by distance.
-
#cross_product(other) ⇒ Float
The cross product of this vector and the other vector.
-
#distance_squared_to(other) ⇒ Float
The squared distance between this point and the other point.
-
#distance_to(other) ⇒ Float
Calculates the distance between self and other.
-
#distance_to_circle(center, radius) ⇒ Float
The distance from this point to the circle.
-
#distance_to_coordinate(x:, y:) ⇒ Float
Distance between this point and coordinate of x and y.
-
#divide(scalar) ⇒ Api::Point2D
(also: #/)
A new point representing this point divided by the scalar.
-
#dot(other) ⇒ Float
The dot product of this vector and the other vector.
-
#lerp(other, scale) ⇒ Api::Point2D
Linear interpolation between this point and another for scale Finds a point on a line between two points at % along the way.
-
#magnitude ⇒ Float
For vector returns the magnitude, synonymous with Math.hypot.
-
#multiply(scalar) ⇒ Api::Point2D
(also: #*)
Returns this point multiplied by the scalar.
-
#normalize ⇒ Api::Point2D
A new point representing the normalized version of this vector (unit length).
-
#offset(x = 0, y = 0) ⇒ Sc2::Position
Creates a new point with x and y which is offset.
-
#offset!(x = 0, y = 0) ⇒ Sc2::Position
Changes this point’s x and y by the supplied offset.
-
#random_offset(offset) ⇒ Sc2::Position
Randomly adjusts both x and y by a range of: -offset..offset.
-
#random_offset!(offset) ⇒ Sc2::Position
Changes this point’s x and y by the supplied offset.
-
#subtract(other) ⇒ Api::Point2D
(also: #-)
Returns a new point representing the difference between this point and the other point/number.
-
#towards(other, distance) ⇒ Api::Point2D
Moves in direction towards other point by distance.
-
#x ⇒ Float
Returns x coordinate.
-
#x=(x) ⇒ Float
Sets x coordinate.
-
#y ⇒ Float
Returns y coordinate.
-
#y=(y) ⇒ Float
Sets y coordinate.
Instance Method Details
#==(other) ⇒ Object
Loose equality matches on floats x and y. We never check z-axis, because the map is single-level. TODO: We should almost certainly introduce TOLERANCE here, but verify it’s cost first.
13 14 15 16 17 18 19 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 13 def ==(other) if other.is_a? Position x == other.x && y == other.y else false end end |
#add(other) ⇒ Api::Point2D Also known as: +
A new point representing the sum of this point and the other point.
24 25 26 27 28 29 30 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 24 def add(other) if other.is_a? Numeric Api::Point2D[x + other, y + other] else Api::Point2D[x + other.x, y + other.y] end end |
#angle_to(other) ⇒ Float
The angle between this vector and the other vector, in radians.
152 153 154 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 152 def angle_to(other) Math.acos(dot(other) / (magnitude * other.magnitude)) end |
#away_from(other, distance) ⇒ Api::Point2D
Moves in direction away from the other point by distance
228 229 230 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 228 def away_from(other, distance) towards(other, -distance) end |
#cross_product(other) ⇒ Float
The cross product of this vector and the other vector.
145 146 147 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 145 def cross_product(other) x * other.y - y * other.x end |
#distance_squared_to(other) ⇒ Float
The squared distance between this point and the other point.
187 188 189 190 191 192 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 187 def distance_squared_to(other) if other.nil? || other == self return 0.0 end (x - other.x) * (y - other.y) end |
#distance_to(other) ⇒ Float
Calculates the distance between self and other
177 178 179 180 181 182 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 177 def distance_to(other) if other.nil? || other == self return 0.0 end Math.hypot(self.x - other.x, self.y - other.y) end |
#distance_to_circle(center, radius) ⇒ Float
The distance from this point to the circle.
204 205 206 207 208 209 210 211 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 204 def distance_to_circle(center, radius) distance_to_center = distance_to(center) if distance_to_center <= radius 0.0 # Point is inside the circle else distance_to_center - radius end end |
#distance_to_coordinate(x:, y:) ⇒ Float
Distance between this point and coordinate of x and y
196 197 198 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 196 def distance_to_coordinate(x:, y:) Math.hypot(self.x - x, self.y - y) end |
#divide(scalar) ⇒ Api::Point2D Also known as: /
Returns A new point representing this point divided by the scalar.
57 58 59 60 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 57 def divide(scalar) raise ZeroDivisionError if scalar.zero? Api::Point2D[x / scalar, y / scalar] end |
#dot(other) ⇒ Float
The dot product of this vector and the other vector.
138 139 140 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 138 def dot(other) x * other.x + y * other.y end |
#lerp(other, scale) ⇒ Api::Point2D
Linear interpolation between this point and another for scale Finds a point on a line between two points at % along the way. 0.0 returns self, 1.0 returns other, 0.5 is halfway.
168 169 170 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 168 def lerp(other, scale) Api::Point2D[x + (other.x - x) * scale, y + (other.y - y) * scale] end |
#magnitude ⇒ Float
For vector returns the magnitude, synonymous with Math.hypot
131 132 133 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 131 def magnitude Math.hypot(x, y) end |
#multiply(scalar) ⇒ Api::Point2D Also known as: *
Returns this point multiplied by the scalar
48 49 50 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 48 def multiply(scalar) Api::Point2D[x * scalar, y * scalar] end |
#normalize ⇒ Api::Point2D
A new point representing the normalized version of this vector (unit length).
158 159 160 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 158 def normalize divide(magnitude) end |
#offset(x = 0, y = 0) ⇒ Sc2::Position
Creates a new point with x and y which is offset
115 116 117 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 115 def offset(x = 0, y = 0) dup.offset!(x, y) end |
#offset!(x = 0, y = 0) ⇒ Sc2::Position
Changes this point’s x and y by the supplied offset
121 122 123 124 125 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 121 def offset!(x = 0, y = 0) self.x += x self.y += y self end |
#random_offset(offset) ⇒ Sc2::Position
Randomly adjusts both x and y by a range of: -offset..offset
100 101 102 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 100 def random_offset(offset) dup.random_offset!(offset) end |
#random_offset!(offset) ⇒ Sc2::Position
Changes this point’s x and y by the supplied offset
106 107 108 109 110 111 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 106 def random_offset!(offset) offset = offset.to_f range = -offset..offset offset!(rand(range), rand(range)) self end |
#subtract(other) ⇒ Api::Point2D Also known as: -
Returns a new point representing the difference between this point and the other point/number.
36 37 38 39 40 41 42 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 36 def subtract(other) if other.is_a? Numeric Api::Point2D[x - other, y - other] else Api::Point2D[x - other.x, y - other.y] end end |
#towards(other, distance) ⇒ Api::Point2D
Moves in direction towards other point by distance
219 220 221 222 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 219 def towards(other, distance) direction = other.subtract(self).normalize add(direction.multiply(distance)) end |
#x ⇒ Float
Returns x coordinate
66 67 68 69 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 66 def x # Perf: Memoizing attributes which are hit hard, show gain @x ||= send(:method_missing, :x) end |
#x=(x) ⇒ Float
Sets x coordinate
73 74 75 76 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 73 def x=(x) send(:method_missing, :x=, x) @x = x end |
#y ⇒ Float
Returns y coordinate
80 81 82 83 84 85 86 87 88 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 80 def y # Bug: Psych implements method 'y' on Kernel, but protobuf uses method_missing to read AbstractMethod # We send method missing ourselves when y to fix this chain. # This is correct, but an unnecessary conditional: # raise NoMethodError unless location == self # Perf: Memoizing attributes which are hit hard, show gain @y ||= send(:method_missing, :y) end |
#y=(y) ⇒ Float
Sets y coordinate
92 93 94 95 |
# File 'lib/sc2ai/protocol/extensions/position.rb', line 92 def y=(y) send(:method_missing, :y=, y) @y = y end |