File Vehicle.hpp¶
File List > astrea > astro > astro > platforms > Vehicle.hpp
Go to the documentation of this file
#pragma once
#include <cassert>
#include <concepts>
#include <memory>
#include <type_traits>
#include <units/units.hpp>
#include <astro/frames/CartesianVector.hpp>
#include <astro/frames/FrameReference.hpp>
#include <astro/frames/frames.hpp>
#include <astro/time/Date.hpp>
#include <astro/types/type_traits.hpp>
namespace astrea {
namespace astro {
template <typename T>
concept HasGetMass = requires(T vehicle) {
{ vehicle.get_mass() } -> std::same_as<Mass>;
};
template <typename T>
concept HasGetRamArea = requires(T vehicle) {
{ vehicle.get_ram_area() } -> std::same_as<SurfaceArea>;
};
template <typename T>
concept HasGetCoefficientOfDrag = requires(T vehicle) {
{ vehicle.get_coefficient_of_drag() } -> std::same_as<Unitless>;
};
template <typename T>
concept HasGetLiftArea = requires(T vehicle) {
{ vehicle.get_lift_area() } -> std::same_as<SurfaceArea>;
};
template <typename T>
concept HasGetCoefficientOfLift = requires(T vehicle) {
{ vehicle.get_coefficient_of_lift() } -> std::same_as<Unitless>;
};
template <typename T>
concept HasGetSolarArea = requires(T vehicle) {
{ vehicle.get_solar_area() } -> std::same_as<SurfaceArea>;
};
template <typename T>
concept HasGetCoefficientOfReflectivity = requires(T vehicle) {
{ vehicle.get_coefficient_of_reflectivity() } -> std::same_as<Unitless>;
};
template <typename T>
concept IsUserDefinedVehicle = requires(T) {
std::is_same<T, remove_cv_ref<T>>::value;
std::is_default_constructible<T>::value;
std::is_copy_constructible<T>::value;
std::is_move_constructible<T>::value;
std::is_destructible<T>::value;
requires HasGetMass<T>;
};
namespace detail {
struct VehicleInnerBase : public virtual FrameReference {
virtual ~VehicleInnerBase() {}
virtual Mass get_mass() const = 0;
virtual SurfaceArea get_ram_area() const = 0;
virtual SurfaceArea get_lift_area() const = 0;
virtual SurfaceArea get_solar_area() const = 0;
virtual Unitless get_coefficient_of_drag() const = 0;
virtual Unitless get_coefficient_of_lift() const = 0;
virtual Unitless get_coefficient_of_reflectivity() const = 0;
virtual std::unique_ptr<VehicleInnerBase> clone() const = 0;
virtual const void* get_ptr() const = 0;
virtual void* get_ptr() = 0;
};
template <typename T>
struct VehicleInner final : public VehicleInnerBase {
VehicleInner() = default;
VehicleInner(const VehicleInner&) = delete;
VehicleInner(VehicleInner&&) = delete;
VehicleInner& operator=(const VehicleInner&) = delete;
VehicleInner& operator=(VehicleInner&&) = delete;
explicit VehicleInner(const T& x) :
_value(x)
{
}
explicit VehicleInner(T&& x) :
_value(std::move(x))
{
}
Mass get_mass() const final { return _value.get_mass(); }
SurfaceArea get_ram_area() const final { return get_ram_area_impl(_value); }
SurfaceArea get_lift_area() const final { return get_lift_area_impl(_value); }
SurfaceArea get_solar_area() const final { return get_solar_area_impl(_value); }
Unitless get_coefficient_of_drag() const final { return get_coefficient_of_drag_impl(_value); }
Unitless get_coefficient_of_lift() const final { return get_coefficient_of_lift_impl(_value); }
Unitless get_coefficient_of_reflectivity() const final { return get_coefficient_of_reflectivity_impl(_value); }
RadiusVector<frames::earth::icrf> get_inertial_position(const Date& date) const override final
{
return _value.get_inertial_position(date);
}
VelocityVector<frames::earth::icrf> get_inertial_velocity(const Date& date) const override final
{
return _value.get_inertial_velocity(date);
}
AccelerationVector<frames::earth::icrf> get_inertial_acceleration(const Date& date) const override final
{
return _value.get_inertial_acceleration(date);
}
std::string get_name() const override final { return _value.get_name(); }
template <typename U>
requires(!HasGetRamArea<U>)
static SurfaceArea get_ram_area_impl(const U&)
{
return 0.0 * mp_units::pow<2>(astrea::detail::minor_distance_unit);
}
template <typename U>
requires(HasGetRamArea<U>)
static SurfaceArea get_ram_area_impl(const U& value)
{
return value.get_ram_area();
}
template <typename U>
requires(!HasGetLiftArea<U>)
static SurfaceArea get_lift_area_impl(const U&)
{
return 0.0 * mp_units::pow<2>(astrea::detail::minor_distance_unit);
}
template <typename U>
requires(HasGetLiftArea<U>)
static SurfaceArea get_lift_area_impl(const U& value)
{
return value.get_lift_area();
}
template <typename U>
requires(!HasGetSolarArea<U>)
static SurfaceArea get_solar_area_impl(const U&)
{
return 0.0 * mp_units::pow<2>(astrea::detail::minor_distance_unit);
}
template <typename U>
requires(HasGetSolarArea<U>)
static SurfaceArea get_solar_area_impl(const U& value)
{
return value.get_solar_area();
}
template <typename U>
requires(!HasGetCoefficientOfDrag<U>)
static Unitless get_coefficient_of_drag_impl(const U&)
{
return 0.0 * mp_units::one;
}
template <typename U>
requires(HasGetCoefficientOfDrag<U>)
static Unitless get_coefficient_of_drag_impl(const U& value)
{
return value.get_coefficient_of_drag();
}
template <typename U>
requires(!HasGetCoefficientOfLift<U>)
static Unitless get_coefficient_of_lift_impl(const U&)
{
return 0.0 * mp_units::one;
}
template <typename U>
requires(HasGetCoefficientOfLift<U>)
static Unitless get_coefficient_of_lift_impl(const U& value)
{
return value.get_coefficient_of_lift();
}
template <typename U>
requires(!HasGetCoefficientOfReflectivity<U>)
static Unitless get_coefficient_of_reflectivity_impl(const U&)
{
return 0.0 * mp_units::one;
}
template <typename U>
requires(HasGetCoefficientOfReflectivity<U>)
static Unitless get_coefficient_of_reflectivity_impl(const U& value)
{
return value.get_coefficient_of_reflectivity();
}
std::unique_ptr<VehicleInnerBase> clone() const final { return std::make_unique<VehicleInner>(_value); }
const void* get_ptr() const final { return &_value; }
void* get_ptr() final { return &_value; }
T _value;
};
} // namespace detail
class Vehicle; // Forward declaration of the Vehicle class
template <typename T>
concept IsGenericallyConstructableVehicle = requires(T) {
requires IsUserDefinedVehicle<T>;
std::negation<std::is_same<Vehicle, remove_cv_ref<T>>>::value;
};
class Vehicle : public FrameReference {
public:
Vehicle();
private:
void generic_ctor_impl();
public:
template <IsGenericallyConstructableVehicle T>
explicit Vehicle(T&& x) :
_ptr(std::make_unique<detail::VehicleInner<remove_cv_ref<T>>>(std::forward<T>(x)))
{
generic_ctor_impl();
}
Vehicle(const Vehicle&);
Vehicle(Vehicle&&) noexcept;
Vehicle& operator=(Vehicle&&) noexcept;
Vehicle& operator=(const Vehicle&);
template <IsGenericallyConstructableVehicle T>
Vehicle& operator=(T&& x)
{
return (*this) = Vehicle(std::forward<T>(x));
}
template <IsGenericallyConstructableVehicle T>
const T* extract() const noexcept
{
auto p = static_cast<const detail::VehicleInner<T>*>(ptr());
return p == nullptr ? nullptr : &(p->_value);
}
Mass get_mass() const { return _ptr->get_mass(); }
SurfaceArea get_ram_area() const { return _ptr->get_ram_area(); }
SurfaceArea get_lift_area() const { return _ptr->get_lift_area(); }
SurfaceArea get_solar_area() const { return _ptr->get_solar_area(); }
Unitless get_coefficient_of_drag() const { return _ptr->get_coefficient_of_drag(); }
Unitless get_coefficient_of_lift() const { return _ptr->get_coefficient_of_lift(); }
Unitless get_coefficient_of_reflectivity() const { return _ptr->get_coefficient_of_reflectivity(); }
RadiusVector<frames::earth::icrf> get_inertial_position(const Date& date) const override
{
return ptr()->get_inertial_position(date);
}
VelocityVector<frames::earth::icrf> get_inertial_velocity(const Date& date) const override
{
return ptr()->get_inertial_velocity(date);
}
AccelerationVector<frames::earth::icrf> get_inertial_acceleration(const Date& date) const override
{
return ptr()->get_inertial_acceleration(date);
}
std::string get_name() const override { return ptr()->get_name(); }
const void* get_ptr() const;
void* get_ptr();
private:
std::unique_ptr<detail::VehicleInnerBase> _ptr;
Mass _mass;
SurfaceArea _ramArea;
SurfaceArea _liftArea;
SurfaceArea _solarArea;
Unitless _coefficientOfDrag;
Unitless _coefficientOfLift;
Unitless _coefficientOfReflectivity;
detail::VehicleInnerBase const* ptr() const
{
assert(_ptr.get() != nullptr);
return _ptr.get();
}
detail::VehicleInnerBase* ptr()
{
assert(_ptr.get() != nullptr);
return _ptr.get();
}
};
} // namespace astro
} // namespace astrea