Skip to content

Commit

Permalink
Implement Vector value object
Browse files Browse the repository at this point in the history
  • Loading branch information
rhannequin committed Feb 1, 2025
1 parent da29613 commit 5c44768
Show file tree
Hide file tree
Showing 15 changed files with 326 additions and 41 deletions.
1 change: 1 addition & 0 deletions lib/astronoby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
require "astronoby/ephem"
require "astronoby/epoch"
require "astronoby/instant"
require "astronoby/vector"
require "astronoby/astronomical_models/ephemeride_lunaire_parisienne"
require "astronoby/astronomical_models/moon_phases_periodic_terms"
require "astronoby/bodies/moon"
Expand Down
15 changes: 13 additions & 2 deletions lib/astronoby/bodies/planet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,20 @@ def compute_barycentric(ephem:, instant:)
velocity = state1.velocity
end

# TODO: Implement Velocity value object
# TODO: Convert velocity into a vector of Velocity

position_vector = Vector[
Distance.from_kilometers(position.x),
Distance.from_kilometers(position.y),
Distance.from_kilometers(position.z)
]

velocity_vector = Vector[velocity.x, velocity.y, velocity.z]

Position::Barycentric.new(
position: position,
velocity: velocity,
position: position_vector,
velocity: velocity_vector,
instant: instant,
target_body: self.class
)
Expand Down
4 changes: 1 addition & 3 deletions lib/astronoby/position/barycentric.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ class Barycentric < ICRF
LIGHT_SPEED_CORRECTION_MAXIMUM_ITERATIONS = 10

# TODO: Move constants into Astronomy::Constants
# TODO: Create Velocity value object
# TODO: Add Velocity.light_speed
# TODO: Wrap Ephem vectors into Distance and Velocity instances?

def initialize(
position:,
Expand All @@ -24,7 +22,7 @@ def initialize(
position: position,
velocity: velocity,
instant: instant,
center_identifier: 0, # TODO: replace with constant
center_identifier: Planet::SOLAR_SYSTEM_BARYCENTER,
target_body: target_body
)
end
Expand Down
2 changes: 0 additions & 2 deletions lib/astronoby/precession.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

require "matrix"

module Astronoby
class Precession
def self.for_equatorial_coordinates(coordinates:, epoch:)
Expand Down
24 changes: 24 additions & 0 deletions lib/astronoby/vector.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

require "matrix"

module Astronoby
class Vector < ::Vector
def initialize(...)
super
freeze
end

def x
self[0]
end

def y
self[1]
end

def z
self[2]
end
end
end
16 changes: 13 additions & 3 deletions spec/astronoby/bodies/earth_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,26 @@
it "returns a Barycentric position" do
time = Time.utc(2025, 2, 7, 12)
instant = Astronoby::Instant.from_time(time)
state = double(position: Vector[1, 2, 3], velocity: Vector[4, 5, 6])
state = double(
position: Ephem::Core::Vector[1, 2, 3],
velocity: Ephem::Core::Vector[4, 5, 6]
)
segment = double(compute_and_differentiate: state)
ephem = double(:[] => segment)
earth = described_class.new(instant: instant, ephem: ephem)

barycentric = earth.barycentric

expect(barycentric).to be_a(Astronoby::Position::Barycentric)
expect(barycentric.position).to eq(Vector[2, 4, 6])
expect(barycentric.velocity).to eq(Vector[8, 10, 12])
expect(barycentric.position)
.to eq(
Astronoby::Vector[
Astronoby::Distance.from_kilometers(2),
Astronoby::Distance.from_kilometers(4),
Astronoby::Distance.from_kilometers(6)
]
)
expect(barycentric.velocity).to eq(Astronoby::Vector[8, 10, 12])
end
end
end
16 changes: 13 additions & 3 deletions spec/astronoby/bodies/jupiter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,26 @@
it "returns a Barycentric position" do
time = Time.utc(2025, 2, 7, 12)
instant = Astronoby::Instant.from_time(time)
state = double(position: Vector[1, 2, 3], velocity: Vector[4, 5, 6])
state = double(
position: Ephem::Core::Vector[1, 2, 3],
velocity: Ephem::Core::Vector[4, 5, 6]
)
segment = double(compute_and_differentiate: state)
ephem = double(:[] => segment)
jupiter = described_class.new(instant: instant, ephem: ephem)

barycentric = jupiter.barycentric

expect(barycentric).to be_a(Astronoby::Position::Barycentric)
expect(barycentric.position).to eq(Vector[1, 2, 3])
expect(barycentric.velocity).to eq(Vector[4, 5, 6])
expect(barycentric.position)
.to eq(
Astronoby::Vector[
Astronoby::Distance.from_kilometers(1),
Astronoby::Distance.from_kilometers(2),
Astronoby::Distance.from_kilometers(3)
]
)
expect(barycentric.velocity).to eq(Astronoby::Vector[4, 5, 6])
end
end
end
16 changes: 13 additions & 3 deletions spec/astronoby/bodies/mars_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,26 @@
it "returns a Barycentric position" do
time = Time.utc(2025, 2, 7, 12)
instant = Astronoby::Instant.from_time(time)
state = double(position: Vector[1, 2, 3], velocity: Vector[4, 5, 6])
state = double(
position: Ephem::Core::Vector[1, 2, 3],
velocity: Ephem::Core::Vector[4, 5, 6]
)
segment = double(compute_and_differentiate: state)
ephem = double(:[] => segment)
mars = described_class.new(instant: instant, ephem: ephem)

barycentric = mars.barycentric

expect(barycentric).to be_a(Astronoby::Position::Barycentric)
expect(barycentric.position).to eq(Vector[1, 2, 3])
expect(barycentric.velocity).to eq(Vector[4, 5, 6])
expect(barycentric.position)
.to eq(
Astronoby::Vector[
Astronoby::Distance.from_kilometers(1),
Astronoby::Distance.from_kilometers(2),
Astronoby::Distance.from_kilometers(3)
]
)
expect(barycentric.velocity).to eq(Astronoby::Vector[4, 5, 6])
end
end
end
16 changes: 13 additions & 3 deletions spec/astronoby/bodies/mercury_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,26 @@
it "returns a Barycentric position" do
time = Time.utc(2025, 2, 7, 12)
instant = Astronoby::Instant.from_time(time)
state = double(position: Vector[1, 2, 3], velocity: Vector[4, 5, 6])
state = double(
position: Ephem::Core::Vector[1, 2, 3],
velocity: Ephem::Core::Vector[4, 5, 6]
)
segment = double(compute_and_differentiate: state)
ephem = double(:[] => segment)
mercury = described_class.new(instant: instant, ephem: ephem)

barycentric = mercury.barycentric

expect(barycentric).to be_a(Astronoby::Position::Barycentric)
expect(barycentric.position).to eq(Vector[2, 4, 6])
expect(barycentric.velocity).to eq(Vector[8, 10, 12])
expect(barycentric.position)
.to eq(
Astronoby::Vector[
Astronoby::Distance.from_kilometers(2),
Astronoby::Distance.from_kilometers(4),
Astronoby::Distance.from_kilometers(6)
]
)
expect(barycentric.velocity).to eq(Astronoby::Vector[8, 10, 12])
end
end
end
16 changes: 13 additions & 3 deletions spec/astronoby/bodies/neptune_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,26 @@
it "returns a Barycentric position" do
time = Time.utc(2025, 2, 7, 12)
instant = Astronoby::Instant.from_time(time)
state = double(position: Vector[1, 2, 3], velocity: Vector[4, 5, 6])
state = double(
position: Ephem::Core::Vector[1, 2, 3],
velocity: Ephem::Core::Vector[4, 5, 6]
)
segment = double(compute_and_differentiate: state)
ephem = double(:[] => segment)
neptune = described_class.new(instant: instant, ephem: ephem)

barycentric = neptune.barycentric

expect(barycentric).to be_a(Astronoby::Position::Barycentric)
expect(barycentric.position).to eq(Vector[1, 2, 3])
expect(barycentric.velocity).to eq(Vector[4, 5, 6])
expect(barycentric.position)
.to eq(
Astronoby::Vector[
Astronoby::Distance.from_kilometers(1),
Astronoby::Distance.from_kilometers(2),
Astronoby::Distance.from_kilometers(3)
]
)
expect(barycentric.velocity).to eq(Astronoby::Vector[4, 5, 6])
end
end
end
52 changes: 42 additions & 10 deletions spec/astronoby/bodies/planet_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
it "returns a Barycentric position" do
time = Time.utc(2025, 2, 7, 12)
instant = Astronoby::Instant.from_time(time)
state = double(position: [1, 2, 3], velocity: [4, 5, 6])
state = double(
position: Ephem::Core::Vector[1, 2, 3],
velocity: Ephem::Core::Vector[4, 5, 6]
)
segment = double(compute_and_differentiate: state)
ephem = double(:[] => segment)
planet = build_planet.new(instant: instant, ephem: ephem)
Expand All @@ -18,21 +21,34 @@
it "returns a Barycentric position with the correct position" do
time = Time.utc(2025, 2, 7, 12)
instant = Astronoby::Instant.from_time(time)
state = double(position: [1, 2, 3], velocity: [4, 5, 6])
state = double(
position: Astronoby::Vector[1, 2, 3],
velocity: Astronoby::Vector[4, 5, 6]
)
segment = double(compute_and_differentiate: state)
ephem = double(:[] => segment)
planet = build_planet.new(instant: instant, ephem: ephem)

barycentric = planet.barycentric

expect(barycentric.position).to eq([1, 2, 3])
expect(barycentric.velocity).to eq([4, 5, 6])
expect(barycentric.position)
.to eq(
Astronoby::Vector[
Astronoby::Distance.from_kilometers(1),
Astronoby::Distance.from_kilometers(2),
Astronoby::Distance.from_kilometers(3)
]
)
expect(barycentric.velocity).to eq(Astronoby::Vector[4, 5, 6])
end

it "returns a Barycentric position with the correct instant" do
time = Time.utc(2025, 2, 7, 12)
instant = Astronoby::Instant.from_time(time)
state = double(position: [1, 2, 3], velocity: [4, 5, 6])
state = double(
position: Astronoby::Vector[1, 2, 3],
velocity: Astronoby::Vector[4, 5, 6]
)
segment = double(compute_and_differentiate: state)
ephem = double(:[] => segment)
planet = build_planet.new(instant: instant, ephem: ephem)
Expand All @@ -45,7 +61,10 @@
it "returns a Barycentric position with the correct target_body" do
time = Time.utc(2025, 2, 7, 12)
instant = Astronoby::Instant.from_time(time)
state = double(position: [1, 2, 3], velocity: [4, 5, 6])
state = double(
position: Astronoby::Vector[1, 2, 3],
velocity: Astronoby::Vector[4, 5, 6]
)
segment = double(compute_and_differentiate: state)
ephem = double(:[] => segment)
planet = build_planet.new(instant: instant, ephem: ephem)
Expand All @@ -59,8 +78,14 @@
it "returns a Barycentric position with the correct position" do
time = Time.utc(2025, 2, 7, 12)
instant = Astronoby::Instant.from_time(time)
state1 = double(position: Vector[1, 2, 3], velocity: Vector[4, 5, 6])
state2 = double(position: Vector[7, 8, 9], velocity: Vector[10, 11, 12])
state1 = double(
position: Astronoby::Vector[1, 2, 3],
velocity: Astronoby::Vector[4, 5, 6]
)
state2 = double(
position: Astronoby::Vector[7, 8, 9],
velocity: Astronoby::Vector[10, 11, 12]
)
segment1 = double(compute_and_differentiate: state1)
segment2 = double(compute_and_differentiate: state2)
ephem = double
Expand All @@ -71,8 +96,15 @@

barycentric = planet.barycentric

expect(barycentric.position).to eq(Vector[8, 10, 12])
expect(barycentric.velocity).to eq(Vector[14, 16, 18])
expect(barycentric.position)
.to eq(
Astronoby::Vector[
Astronoby::Distance.from_kilometers(8),
Astronoby::Distance.from_kilometers(10),
Astronoby::Distance.from_kilometers(12)
]
)
expect(barycentric.velocity).to eq(Astronoby::Vector[14, 16, 18])
end
end

Expand Down
16 changes: 13 additions & 3 deletions spec/astronoby/bodies/saturn_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,26 @@
it "returns a Barycentric position" do
time = Time.utc(2025, 2, 7, 12)
instant = Astronoby::Instant.from_time(time)
state = double(position: Vector[1, 2, 3], velocity: Vector[4, 5, 6])
state = double(
position: Ephem::Core::Vector[1, 2, 3],
velocity: Ephem::Core::Vector[4, 5, 6]
)
segment = double(compute_and_differentiate: state)
ephem = double(:[] => segment)
saturn = described_class.new(instant: instant, ephem: ephem)

barycentric = saturn.barycentric

expect(barycentric).to be_a(Astronoby::Position::Barycentric)
expect(barycentric.position).to eq(Vector[1, 2, 3])
expect(barycentric.velocity).to eq(Vector[4, 5, 6])
expect(barycentric.position)
.to eq(
Astronoby::Vector[
Astronoby::Distance.from_kilometers(1),
Astronoby::Distance.from_kilometers(2),
Astronoby::Distance.from_kilometers(3)
]
)
expect(barycentric.velocity).to eq(Astronoby::Vector[4, 5, 6])
end
end
end
16 changes: 13 additions & 3 deletions spec/astronoby/bodies/uranus_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,26 @@
it "returns a Barycentric position" do
time = Time.utc(2025, 2, 7, 12)
instant = Astronoby::Instant.from_time(time)
state = double(position: Vector[1, 2, 3], velocity: Vector[4, 5, 6])
state = double(
position: Ephem::Core::Vector[1, 2, 3],
velocity: Ephem::Core::Vector[4, 5, 6]
)
segment = double(compute_and_differentiate: state)
ephem = double(:[] => segment)
uranus = described_class.new(instant: instant, ephem: ephem)

barycentric = uranus.barycentric

expect(barycentric).to be_a(Astronoby::Position::Barycentric)
expect(barycentric.position).to eq(Vector[1, 2, 3])
expect(barycentric.velocity).to eq(Vector[4, 5, 6])
expect(barycentric.position)
.to eq(
Astronoby::Vector[
Astronoby::Distance.from_kilometers(1),
Astronoby::Distance.from_kilometers(2),
Astronoby::Distance.from_kilometers(3)
]
)
expect(barycentric.velocity).to eq(Astronoby::Vector[4, 5, 6])
end
end
end
Loading

0 comments on commit 5c44768

Please sign in to comment.