<commit_before>require "kepler/universal_formulation"
require "kepler/lagrange"
require "kepler/laguerre"

module Kepler
  class Orbit
    include UniversalFormulation
    include Lagrange

    attr_accessor :r, :v

    def initialize(r, v)
      @r = r
      @v = v
    end

    def self.from_params(params)
      params = expanded_params(params)

      r_p = perifocal_position(params[:angular_momentum], params[:eccentricity], params[:true_anomaly])
      v_p = perifocal_velocity(params[:angular_momentum], params[:eccentricity], params[:true_anomaly])

      q = transform_matrix(params[:argument_of_periapsis], params[:inclination], params[:right_ascension])

      r = q * r_p
      v = q * v_p

      self.new(r, v)
    end

    def self.expanded_params(params)
      required_params = [
        %i(semimajor_axis eccentricity),
        %i(semilatus_rectum eccentricity),
        %i(apogee perigee)
      ]

      param_set = required_params.find { |rp| rp & params.keys == rp }
      raise ArgumentError, "Invalid parameter set" if param_set.nil?

      default_params = {
        inclination: 0,
        argument_of_periapsis: 0,
        right_ascension: 0,
        true_anomaly: 0,
        eccentricity: 0
      }

      params = default_params.merge(params)

      if param_set.include?(:apogee) && param_set.include?(:perigee)
        params[:semimajor_axis] = ((EARTH_RADIUS * 2) + params[:apogee] + params[:perigee]) / 2
        params[:eccentricity] = (params[:semimajor_axis] / (EARTH_RADIUS + params[:perigee])) - 1
      elsif param_set.include?(:semilatus_rectum)
        params[:semimajor_axis] = params[:semilatus_rectum] / (1 - (params[:eccentricity] ** 2))
      end

      unless param_set.include?(:semilatus_rectum)
        params[:semilatus_rectum] = params[:semimajor_axis] * (1 - (params[:eccentricity] ** 2))
      end

      params[:angular_momentum] = Math.sqrt(params[:semilatus_rectum] * MU)

      params
    end

    # matrix to transform vectors with perifocal basis to vectors with
    # geocentric equatorial basis
    # all args are scalar
    def self.transform_matrix(argument_of_periapsis, inclination, right_ascension)
      w = argument_of_periapsis.to_rad
      i = inclination.to_rad
      omega = right_ascension.to_rad

      Matrix[
        [-Math.sin(omega) * Math.cos(i) * Math.sin(w) + (Math.cos(omega) * Math.cos(w)),
         -Math.sin(omega) * Math.cos(i) * Math.cos(w) - (Math.cos(omega) * Math.sin(w)),
         Math.sin(omega) * Math.sin(i)],
        [Math.cos(omega) * Math.cos(i) * Math.sin(w) + (Math.sin(omega) * Math.cos(w)),
         Math.cos(omega) * Math.cos(i) * Math.cos(w) - (Math.sin(omega) * Math.sin(w)),
         -Math.cos(omega) * Math.sin(i)],
        [Math.sin(i) * Math.sin(w),
         Math.sin(i) * Math.cos(w),
         Math.cos(i)]
      ]<commit_msg>refactoring Orbit.transform_matrix<commit_after>require "kepler/universal_formulation"
require "kepler/lagrange"
require "kepler/laguerre"

module Kepler
  class Orbit
    include UniversalFormulation
    include Lagrange

    attr_accessor :r, :v

    def initialize(r, v)
      @r = r
      @v = v
    end

    def self.from_params(params)
      params = expanded_params(params)

      r_p = perifocal_position(params[:angular_momentum], params[:eccentricity], params[:true_anomaly])
      v_p = perifocal_velocity(params[:angular_momentum], params[:eccentricity], params[:true_anomaly])

      q = transform_matrix(params[:argument_of_periapsis], params[:inclination], params[:right_ascension])

      r = q * r_p
      v = q * v_p

      self.new(r, v)
    end

    def self.expanded_params(params)
      required_params = [
        %i(semimajor_axis eccentricity),
        %i(semilatus_rectum eccentricity),
        %i(apogee perigee)
      ]

      param_set = required_params.find { |rp| rp & params.keys == rp }
      raise ArgumentError, "Invalid parameter set" if param_set.nil?

      default_params = {
        inclination: 0,
        argument_of_periapsis: 0,
        right_ascension: 0,
        true_anomaly: 0,
        eccentricity: 0
      }

      params = default_params.merge(params)

      if param_set.include?(:apogee) && param_set.include?(:perigee)
        params[:semimajor_axis] = ((EARTH_RADIUS * 2) + params[:apogee] + params[:perigee]) / 2
        params[:eccentricity] = (params[:semimajor_axis] / (EARTH_RADIUS + params[:perigee])) - 1
      elsif param_set.include?(:semilatus_rectum)
        params[:semimajor_axis] = params[:semilatus_rectum] / (1 - (params[:eccentricity] ** 2))
      end

      unless param_set.include?(:semilatus_rectum)
        params[:semilatus_rectum] = params[:semimajor_axis] * (1 - (params[:eccentricity] ** 2))
      end

      params[:angular_momentum] = Math.sqrt(params[:semilatus_rectum] * MU)

      params
    end

    # matrix to transform vectors with perifocal basis to vectors with
    # geocentric equatorial basis
    # all args are scalar
    def self.transform_matrix(argument_of_periapsis, inclination, right_ascension)
      w = argument_of_periapsis.to_rad
      i = inclination.to_rad
      omega = right_ascension.to_rad

      sin_omega = Math.sin(omega)
      cos_omega = Math.cos(omega)
      sin_i = Math.sin(i)
      cos_i = Math.cos(i)
      sin_w = Math.sin(w)
      cos_w = Math.cos(w)

      Matrix[
        [-sin_omega * cos_i * sin_w + (cos_omega * cos_w),
         -sin_omega * cos_i * cos_w - (cos_omega * sin_w),
         sin_omega * sin_i],
        [cos_omega * cos_i * sin_w + (sin_omega * cos_w),
         cos_omega * cos_i * cos_w - (sin_omega * sin_w),
         -cos_omega * sin_i],
        [sin_i * sin_w,
         sin_i * cos_w,
         cos_i]
      ]
{'fraction_non_alphanumeric': 0.1220112517580872, 'fraction_numerical': 0.004219409282700422, 'mean_word_length': 2.86743711760707, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7107221', 'n_tokens_mistral': 2040, 'n_tokens_neox': 1955, 'n_words': 367}