Module: Math2D::Utils2D

Defined in:
lib/math2d/utils2d.rb

Overview

Note:

Most if not all methods descriptions here present come from the p5.js website.

A collection of useful Mathematical tools in 2D space

See Also:

Author:

Constant Summary collapse

HALF_PI =

Half the mathematical constant PI.

Math::PI / 2
QUARTER_PI =

A quarter of the mathematical constant PI.

Math::PI / 4
TWO_PI =

Twice the mathematical constant PI, also called TAU.

TAU = Math::PI * 2
DEG2RAD =
Note:

Can be used as a substitute to Utils2D.to_rad.

Multiplication constant to convert a value in degrees to radians.

Math::PI / 180
RAD2DEG =
Note:

Can be used as a substitute to Utils2D.to_deg.

Multiplication constant to convert a value in radians to degrees.

180 / Math::PI

Class Method Summary collapse

Class Method Details

.constrain(x, a, b) ⇒ Numeric Also known as: clamp

Constrains a value x between a minimum value a and maximum value b.

Parameters:

  • x (Numeric)
  • a (Numeric)
  • b (Numeric)

Returns:

  • (Numeric)


106
107
108
# File 'lib/math2d/utils2d.rb', line 106

def self.constrain(x, a, b)
  [[x, a].max, b].min
end

.distance(x1, y1, x2, y2) ⇒ Float

Returns the distance between two cartesian points.

Parameters:

  • x1 (Numeric)
  • y1 (Numeric)
  • x2 (Numeric)
  • y2 (Numeric)

Returns:

  • (Float)


46
47
48
# File 'lib/math2d/utils2d.rb', line 46

def self.distance(x1, y1, x2, y2)
  Math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
end

.grayscale(val = nil) ⇒ Array<Float> Also known as: greyscale

If no argument is passed, randomly generates a grayscale RGB array. Otherwise, returns a grayscale array with that argument normalized.

Parameters:

  • val (Numeric) (defaults to: nil)

Returns:

  • (Array<Float>)


150
151
152
153
154
155
156
157
# File 'lib/math2d/utils2d.rb', line 150

def self.grayscale(val = nil)
  c = if val
        normalize(val, 0, 255).abs
      else
        rand
      end
  [c, c, c, 1.0]
end

.hsv_to_rgb(color) ⇒ Array<Float>

Note:

This method assumes that both the RGB and HSV color arrays are in Linear RGB/HSV (also called RBG/HSV 0-1),

Converts an HSV color array (h,s,v,a) color to the RGB (r,g,b,a) color space.

where each component ranges from 0.0 to 1.0.

Parameters:

  • (Array<Numeric>)

Returns:

  • (Array<Float>)


252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/math2d/utils2d.rb', line 252

def self.hsv_to_rgb(color)
  h = color[0]
  s = color[1]
  v = color[2]
  a = color[3]
  i = (h * 6).floor
  f = h * 6 - i
  pp = v * (1 - s)
  q = v * (1 - f * s)
  t = v * (1 - (1 - f) * s)

  case i % 6
  when 0
    r = v
    g = t
    b = pp
  when 1
    r = q
    g = v
    b = pp
  when 2
    r = pp
    g = v
    b = t
  when 3
    r = pp
    g = q
    b = v
  when 4
    r = t
    g = pp
    b = v
  when 5
    r = v
    g = pp
    b = q
  end

  [r, g, b, a]
end

.inverse_lerp(a, b, value) ⇒ Float

Being the inverse of #lerp, it calculates the interpolation parameter t

of the Lerp method given a range [+a+, +b+] and a interpolant value of +value+.

Parameters:

  • a (Numeric)
  • b (Numeric)
  • value (Numeric)

Returns:

  • (Float)


71
72
73
# File 'lib/math2d/utils2d.rb', line 71

def self.inverse_lerp(a, b, value)
  (value - a) / (b - a).to_f
end

.lerp(a, b, amt) ⇒ Float

Calculates a number between two numbers at a specific increment. The amt parameter is the amount to interpolate between the two values where 0.0 equal to the first point, 0.1 is very near the first point, 0.5 is half-way in between, and 1.0 is equal to the second point.

Parameters:

  • a (Numeric)
  • b (Numeric)
  • amt (Numeric)

Returns:

  • (Float)


60
61
62
# File 'lib/math2d/utils2d.rb', line 60

def self.lerp(a, b, amt)
  (b - a) * (3.0 - amt * 2.0) * amt * amt + a
end

.lerp_hue(a, b, amt) ⇒ Array<Float>

Note:

Both colors are converted internally to HSV and then converted back to RGB 0-1 at the end.

Interpolates two RGB (r,g,b,a) colors a and b in the HSV color space by an amount amt. This method is preferred over lerp_rgb when working with intensity graphs (i.e. temperature, probability density etc.)

Parameters:

  • a (Array<Numeric>)
  • b (Array<Numeric>)
  • amt (Numeric)

Returns:

  • (Array<Float>)


188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/math2d/utils2d.rb', line 188

def self.lerp_hue(a, b, amt)
  a = rgb_to_hsv(a)
  b = rgb_to_hsv(b)
  d = (b[0] - a[0]).abs
  if a[0] > b[0]
    a, b = b, a
    amt = 1 - amt
  end
  if d > 0.5
    a[0] += 1
    h = (a[0] + amt * (b[0] - a[0])) % 1
  else
    h = a[0] + amt * d
  end
  hsv_to_rgb(
    [
      h,
      lerp(a[1], b[1], amt),
      lerp(a[2], b[2], amt),
      lerp(a[3], b[3], amt)
    ]
  )
end

.lerp_rgb(a, b, amt) ⇒ Array<Float>

Interpolates two RGB (r,g,b,a) colors a and b by an amount amt.

Parameters:

  • a (Array<Numeric>)
  • b (Array<Numeric>)
  • amt (Numeric)

Returns:

  • (Array<Float>)


169
170
171
172
173
174
175
176
# File 'lib/math2d/utils2d.rb', line 169

def self.lerp_rgb(a, b, amt)
  [
    lerp(a[0], b[0], amt),
    lerp(a[1], b[1], amt),
    lerp(a[2], b[2], amt),
    lerp(a[3], b[3], amt)
  ]
end

.map(value, a1, a2, b1, b2) ⇒ Float

Re-maps a number from one range (a1..a2) to another (b1..b2).

Parameters:

  • value (Numeric)
  • a1 (Numeric)
  • a2 (Numeric)
  • b1 (Numeric)
  • b2 (Numeric)

Returns:

  • (Float)

Raises:

  • (ArgumentError)


83
84
85
86
87
88
# File 'lib/math2d/utils2d.rb', line 83

def self.map(value, a1, a2, b1, b2)
  raise ArgumentError, 'Division by 0 - a1 cannot be equal to a2' if a2 == a1

  slope = 1.0 * (b2 - b1) / (a2 - a1)
  b1 + slope * (value - a1)
end

.noise(x, y = 0) ⇒ Float

Returns the Perlin noise value at specified coordinates. Perlin noise is a random sequence generator producing a more naturally ordered, harmonic succession of numbers compared to the standard rand() method. The main difference to the rand() method is that Perlin noise is defined in an infinite n-dimensional space where each pair of coordinates corresponds to a fixed semi-random value. Utils2D can compute 1D and 2D noise, depending on the number of coordinates given. The resulting value will always be between 0.0 and 1.0.

Parameters:

  • x (Numeric)
  • y (Numeric) (defaults to: 0)

Returns:

  • (Float)

See Also:



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/math2d/utils2d.rb', line 126

def self.noise(x, y = 0)
  x0 = x.to_i
  x1 = x0 + 1
  y0 = y.to_i
  y1 = y0 + 1

  sx = x - x0.to_f
  sy = y - y0.to_f

  n0 = dot_grid_gradient(x0, y0, x, y)
  n1 = dot_grid_gradient(x1, y0, x, y)
  ix0 = lerp(n0, n1, sx)

  n0 = dot_grid_gradient(x0, y1, x, y)
  n1 = dot_grid_gradient(x1, y1, x, y)
  ix1 = lerp(n0, n1, sx)
  lerp(ix0, ix1, sy)
end

.normalize(value, a, b) ⇒ Float

Normalizes a number from another range (a..b) into a value between 0 and 1.

Parameters:

  • value (Numeric)
  • a (Numeric)
  • b (Numeric)

Returns:

  • (Float)


96
97
98
# File 'lib/math2d/utils2d.rb', line 96

def self.normalize(value, a, b)
  map(value, a, b, 0.0, 1.0)
end

.rgb_to_hsv(color) ⇒ Array<Float>

Note:

This method assumes that both the RGB and HSV color arrays are in Linear RGB/HSV (also called RBG/HSV 0-1),

Converts an RGB color array (r,g,b,a) color to the HSV (h,s,v,a) color space.

where each component ranges from 0.0 to 1.0.

Parameters:

  • (Array<Numeric>)

Returns:

  • (Array<Float>)


219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/math2d/utils2d.rb', line 219

def self.rgb_to_hsv(color)
  r = color[0]
  g = color[1]
  b = color[2]
  a = color[3]
  max = [r, g, b].max
  min = [r, g, b].min
  v = max
  d = max - min
  s = max.zero? ? 0 : d / max
  if max == min
    h = 0
  else
    case max
    when r
      h = (g - b) / d + (g < b ? 6 : 0)
    when g
      h = (b - r) / d + 2
    when b
      h = (r - g) / d + 4
    end
    h /= 6
  end
  [h, s, v, a]
end

.to_deg(angle) ⇒ Float

Returns angle radians in degrees.

Parameters:

  • angle (Numeric)

Returns:

  • (Float)


27
28
29
# File 'lib/math2d/utils2d.rb', line 27

def self.to_deg(angle)
  angle * RAD2DEG
end

.to_rad(angle) ⇒ Float

Returns angle degrees in radians.

Parameters:

  • angle (Numeric)

Returns:

  • (Float)


35
36
37
# File 'lib/math2d/utils2d.rb', line 35

def self.to_rad(angle)
  angle * DEG2RAD
end