9#include "../astro_context.hpp"
10#include "../centers.hpp"
11#include "../ffi_core.hpp"
12#include "../frames.hpp"
15#include <qtty/qtty.hpp>
26template <
typename C,
typename F,
typename U>
struct Position;
42 static_assert(frames::is_frame_v<F>,
"F must be a valid frame tag");
89 template <
typename Target>
92 if constexpr (std::is_same_v<F, Target>) {
99 "cartesian::Direction::to_frame");
107 template <
typename Target>
110 if constexpr (std::is_same_v<F, Target>) {
118 "cartesian::Direction::to_frame_with");
126 template <
typename Target>
136 coordinates::detail::write_frame<F>(os);
137 return os <<
" direction (x=" << dir.
x <<
", y=" << dir.
y <<
", z=" << dir.
z <<
')';
141template <
typename C,
typename F,
typename U>
struct Position;
161 static_assert(frames::is_frame_v<F>,
"F must be a valid frame tag");
171 Displacement(
double x_,
double y_,
double z_) : comp_x(U(x_)), comp_y(U(y_)), comp_z(U(z_)) {}
173 U
x()
const {
return comp_x; }
174 U
y()
const {
return comp_y; }
175 U
z()
const {
return comp_z; }
182 const double vx = comp_x.value();
183 const double vy = comp_y.value();
184 const double vz = comp_z.value();
185 return U(sqrt(vx * vx + vy * vy + vz * vz));
213 return Displacement(comp_x * scalar, comp_y * scalar, comp_z * scalar);
222 template <
typename Target>
225 if constexpr (std::is_same_v<F, Target>) {
228 siderust_cartesian_pos_t out{};
230 comp_x.value(), comp_y.value(), comp_z.value(),
233 "cartesian::Displacement::to_frame");
241 template <
typename Target>
244 if constexpr (std::is_same_v<F, Target>) {
247 siderust_cartesian_pos_t out{};
249 check_status(siderust_cartesian_dir_transform_frame_with_context(
250 comp_x.value(), comp_y.value(), comp_z.value(),
252 jd.value(), fctx.
get(), &out),
253 "cartesian::Displacement::to_frame_with");
262template <
typename F,
typename U>
264 coordinates::detail::write_frame<F>(os);
265 return os <<
" displacement (dx=" << d.
x() <<
", dy=" << d.
y() <<
", dz=" << d.
z() <<
')';
271template <
typename F,
typename U>
286template <
typename C,
typename F,
typename U>
struct Position {
287 static_assert(frames::is_frame_v<F>,
"F must be a valid frame tag");
288 static_assert(centers::is_center_v<C>,
"C must be a valid center tag");
306 const double vx =
comp_x.value();
307 const double vy =
comp_y.value();
308 const double vz =
comp_z.value();
309 return U(
sqrt(vx * vx + vy * vy + vz * vz));
347 template <
typename Target>
350 if constexpr (std::is_same_v<F, Target>) {
356 "cartesian::Position::to_frame");
364 template <
typename Target>
367 if constexpr (std::is_same_v<F, Target>) {
374 "cartesian::Position::to_frame_with");
382 template <
typename Target>
399 template <
typename TargetC>
402 if constexpr (std::is_same_v<C, TargetC>) {
404 }
else if constexpr (std::is_same_v<F, frames::EclipticMeanJ2000>) {
409 "cartesian::Position::to_center");
432 template <
typename TargetC,
typename TargetF>
433 std::enable_if_t<frames::has_frame_transform_v<F, TargetF> &&
434 centers::has_center_transform_v<C, TargetC>,
487template <
typename C,
typename F,
typename U>
489 coordinates::detail::write_center_frame<C, F>(os);
490 return os <<
" (x=" << pos.
x() <<
", y=" << pos.
y() <<
", z=" << pos.
z() <<
')';
const siderust_context_t * get() const
Displacement< F, U > operator*(double scalar, const Displacement< F, U > &d)
Scale a displacement by a scalar (scalar on left).
std::ostream & operator<<(std::ostream &os, const Direction< F > &dir)
Stream operator for cartesian::Direction.
tempoch::EncodedTime< Scale, Format > Time
void check_status(siderust_status_t status, const char *operation)
Shared helpers for human-readable coordinate stream output.
A unit-vector direction in Cartesian form, compile-time frame-tagged.
double x
X component (unitless).
auto to(const Time< TT, JD > &jd) const -> decltype(this->template to_frame< Target >(jd))
Shorthand: .to<Target>(jd) (calls to_frame).
double angle_to(const Direction &other) const
Angle between this direction and another, in radians.
double y
Y component (unitless).
static constexpr siderust_frame_t frame_id()
Direction(double x_, double y_, double z_)
std::enable_if_t< frames::has_frame_transform_v< F, Target >, Direction< Target > > to_frame_with(const Time< TT, JD > &jd, const AstroContext &ctx) const
Transform this direction with an explicit astronomical context.
double dot(const Direction &other) const
Dot product of two unit-direction vectors.
double z
Z component (unitless).
std::enable_if_t< frames::has_frame_transform_v< F, Target >, Direction< Target > > to_frame(const Time< TT, JD > &jd) const
Transform this direction to a different reference frame.
A 3D Cartesian displacement (free vector), compile-time frame-tagged.
Displacement(U x_, U y_, U z_)
Displacement operator-(const Displacement &other) const
Subtract two displacements.
Displacement operator-() const
Negate a displacement.
Displacement operator+(const Displacement &other) const
Add two displacements.
Displacement(double x_, double y_, double z_)
static constexpr siderust_frame_t frame_id()
Displacement operator*(double scalar) const
Scale a displacement by a scalar.
std::enable_if_t< frames::has_frame_transform_v< F, Target >, Displacement< Target, U > > to_frame_with(const Time< TT, JD > &jd, const AstroContext &ctx) const
Transform this displacement with an explicit astronomical context.
std::enable_if_t< frames::has_frame_transform_v< F, Target >, Displacement< Target, U > > to_frame(const Time< TT, JD > &jd) const
Transform this displacement to a different reference frame.
U magnitude() const
Magnitude of the displacement vector.
A 3D Cartesian position, compile-time tagged by center, frame, unit.
Position operator+(const Displacement< F, U > &displacement) const
Translate a position by a displacement.
std::enable_if_t< frames::has_frame_transform_v< F, Target >, Position< C, Target, U > > to_frame_with(const Time< TT, JD > &jd, const AstroContext &ctx) const
Transform this position with an explicit astronomical context.
std::enable_if_t< frames::has_frame_transform_v< F, TargetF > &¢ers::has_center_transform_v< C, TargetC >, Position< TargetC, TargetF, U > > transform(const Time< TT, JD > &jd) const
Combined frame + center transform in one call.
static constexpr siderust_center_t center_id()
siderust_cartesian_pos_t to_c() const
Convert to C FFI struct.
U distance_to(const Position &other) const
Position operator-(const Displacement< F, U > &displacement) const
Translate a position backwards by a displacement.
static Position from_c(const siderust_cartesian_pos_t &c)
Create from C FFI struct (ignoring runtime frame/center - trust the type).
std::enable_if_t< centers::has_center_transform_v< C, TargetC >, Position< TargetC, F, U > > to_center(const Time< TT, JD > &jd) const
Transform this position to a different reference center (same frame).
spherical::Position< C, F, U > to_spherical() const
Convert this cartesian position to a spherical Position<C,F,U>.
auto to(const Time< TT, JD > &jd) const -> decltype(this->template to_frame< Target >(jd))
Shorthand: .to<Target>(jd) (calls to_frame).
Position(double x_, double y_, double z_)
std::enable_if_t< frames::has_frame_transform_v< F, Target >, Position< C, Target, U > > to_frame(const Time< TT, JD > &jd) const
Transform this position to a different reference frame (same center).
U magnitude() const
Magnitude of the position vector (alias for distance()).
Position(U x_, U y_, U z_)
Displacement< F, U > operator-(const Position &other) const
Subtract two positions in the same center/frame/unit.
static constexpr siderust_frame_t frame_id()
SFINAE helper: every frame tag must provide these static members.
A spherical position (direction + distance), compile-time tagged.