Module: Astronoby::Util::Maths

Defined in:
lib/astronoby/util/maths.rb

Class Method Summary collapse

Class Method Details

.cross_product(a, b) ⇒ Object



12
13
14
15
16
17
18
# File 'lib/astronoby/util/maths.rb', line 12

def cross_product(a, b)
  [
    a[1] * b[2] - a[2] * b[1],
    a[2] * b[0] - a[0] * b[2],
    a[0] * b[1] - a[1] * b[0]
  ]
end

.dot_product(a, b) ⇒ Object



8
9
10
# File 'lib/astronoby/util/maths.rb', line 8

def dot_product(a, b)
  a.zip(b).sum { |x, y| x * y }
end

.linear_interpolate(x1, x2, y1, y2, target_y = 0) ⇒ Numeric

Linear interpolation between two points

Parameters:

  • x1 (Numeric)

    First x value

  • x2 (Numeric)

    Second x value

  • y1 (Numeric)

    First y value

  • y2 (Numeric)

    Second y value

  • target_y (Numeric) (defaults to: 0)

    Target y value (default: 0)

Returns:

  • (Numeric)

    Interpolated x value where y=target_y



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/astronoby/util/maths.rb', line 49

def self.linear_interpolate(x1, x2, y1, y2, target_y = 0)
  # Handle horizontal line case (avoid division by zero)
  if (y2 - y1).abs < 1e-10
    # If target_y matches the line's y-value (within precision), return
    # midpoint. Otherwise, return one of the endpoints (no unique solution
    # exists)
    return ((target_y - y1).abs < 1e-10) ? (x1 + x2) / 2.0 : x1
  end

  # Handle vertical line case
  if (x2 - x1).abs < 1e-10
    # For a vertical line, there's only one x-value possible
    return x1
  end

  # Standard linear interpolation formula
  x1 + (target_y - y1) * (x2 - x1) / (y2 - y1)
end

.linspace(start, stop, num = 50, endpoint = true) ⇒ Array<Numeric>

Creates an array of evenly spaced values between start and stop.

Parameters:

  • start (Numeric)

    The starting value of the sequence

  • stop (Numeric)

    The end value of the sequence

  • num (Integer) (defaults to: 50)

    Number of samples to generate. Default is 50

  • endpoint (Boolean) (defaults to: true)

    If true, stop is the last sample. Otherwise, it is not included. Default is true

Returns:

  • (Array<Numeric>)

    Array of evenly spaced values

Raises:

  • (ArgumentError)

    If num is less than 1



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/astronoby/util/maths.rb', line 76

def linspace(start, stop, num = 50, endpoint = true)
  raise ArgumentError, "Number of samples must be at least 1" if num < 1
  return [start] if num == 1

  step = if endpoint
    (stop - start) / (num - 1).to_f
  else
    (stop - start) / num.to_f
  end

  result = Array.new(num)
  current = start

  (num - 1).times do |i|
    result[i] = current
    current += step
  end

  result[num - 1] = endpoint ? stop : current
  result
end

.quadratic_maximum(t1, t2, t3, alt1, alt2, alt3) ⇒ ::Time

Find maximum altitude using quadratic interpolation

Parameters:

  • t1,

    t2, t3 [Time] Three consecutive times

  • alt1,

    alt2, alt3 [Float] Corresponding altitudes

Returns:

  • (::Time)

    Time of maximum altitude



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/astronoby/util/maths.rb', line 24

def quadratic_maximum(t1, t2, t3, alt1, alt2, alt3)
  # Convert to float seconds for arithmetic
  x1, x2, x3 = t1.to_f, t2.to_f, t3.to_f
  y1, y2, y3 = alt1, alt2, alt3

  # Quadratic interpolation formula
  denom = (x1 - x2) * (x1 - x3) * (x2 - x3)
  a = (x3 * (y2 - y1) + x2 * (y1 - y3) + x1 * (y3 - y2)) / denom
  b = (x3 * x3 * (y1 - y2) +
    x2 * x2 * (y3 - y1) +
    x1 * x1 * (y2 - y3)) / denom

  # Maximum is at -b/2a
  max_t = -b / (2 * a)

  ::Time.at(max_t)
end