This commit is contained in:
Timur A. Fatkhullin 2025-10-26 02:22:39 +03:00
parent ec27cd981a
commit bdfc5dbc1c
2 changed files with 250 additions and 69 deletions

View File

@ -501,6 +501,7 @@ struct MccPositionControls : CCTE_T, HARDWARE_T, PCM_T {
static_assert(mcc_julday_c<MccJulianDay>, "");
static_assert(mcc_celestial_point_c<MccCelestialPoint>, "");
static_assert(mcc_pointing_target_coord_c<MccGenericPointingTarget<double>>, "");
static_assert(mcc_telemetry_data_c<MccTelemetryData>, "");
@ -569,6 +570,30 @@ protected:
return {};
}
template <traits::mcc_input_char_range IR>
std::error_code parseHourRepr(const IR& bytes, double& ang_value)
{
std::optional<double> ang;
ang = mcc::utils::parsAngleString(bytes, true);
if (ang) {
ang_value = MccAngle(ang.value(), MccDegreeTag{});
} else {
return std::make_error_code(std::errc::invalid_argument);
}
}
template <traits::mcc_input_char_range IR>
std::error_code parseDegreeRepr(const IR& bytes, double& ang_value)
{
std::optional<double> ang;
ang = mcc::utils::parsAngleString(bytes);
if (ang) {
ang_value = MccAngle(ang.value(), MccDegreeTag{});
} else {
return std::make_error_code(std::errc::invalid_argument);
}
}
};
// base class
@ -774,12 +799,15 @@ public:
pt.Y = MccAngle(ang2.value(), mcc::MccDegreeTag{});
mcc_copy_celestial_point(pt, &value);
return {};
}
};
class MccEqtHrzCoordsSerializer : public MccCoordinateSerializer
{
public:
template <mcc_eqt_hrz_coord_c T, traits::mcc_output_char_range OR>
void operator()(const T& value, OR& bytes)
{
@ -826,85 +854,221 @@ class MccEqtHrzCoordsSerializer : public MccCoordinateSerializer
class MccEqtHrzCoordsDeserializer : public MccCoordinateDeserializer
{
public:
template <traits::mcc_input_char_range IR, mcc_eqt_hrz_coord_c T>
std::error_code operator()(IR&& bytes, T& value)
{
// valid format: RA, DEC, HA, AZ, ZD, ALT, X, Y, pair-kind, time-point
// in the case of sexagesimal input the X,Y coordinates will be interpretated
// according to value.pair_kind field
auto els = splitToElements(std::forward<IR>(bytes));
if (els.size() < 10) {
return std::make_error_code(std::errc::invalid_argument);
}
MccEqtHrzCoords pt;
pt.pair_kind = MccCoordStrToPairKind(els[8]);
if (pt.pair_kind == MccCoordPairKind::COORDS_KIND_UNKNOWN) {
return std::make_error_code(std::errc::invalid_argument);
}
auto err = parseTimePoint(els[9], pt);
if (err) {
return err;
}
err = parseHourRepr(els[0], pt.RA_APP);
if (err) {
return err;
}
err = parseDegreeRepr(els[1], pt.DEC_APP);
if (err) {
return err;
}
err = parseHourRepr(els[2], pt.HA);
if (err) {
return err;
}
err = parseDegreeRepr(els[4], pt.AZ);
if (err) {
return err;
}
err = parseDegreeRepr(els[5], pt.ZD);
if (err) {
return err;
}
err = parseDegreeRepr(els[6], pt.ALT);
if (err) {
return err;
}
switch (value.pair_kind) {
case MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
case MccCoordPairKind::COORDS_KIND_RADEC_APP:
case MccCoordPairKind::COORDS_KIND_HADEC_APP:
err = parseHourRepr(els[7], pt.X);
break;
default:
err = parseDegreeRepr(els[7], pt.X);
}
if (err) {
return err;
}
err = parseDegreeRepr(els[8], pt.Y);
if (err) {
return err;
}
mcc_copy_eqt_hrz_coord(pt, &value);
return {};
}
};
/**/
class MccPointingTargetSerializer : public MccCoordinateSerializer
{
public:
template <mcc_pointing_target_coord_c T, traits::mcc_output_char_range OR>
void operator()(const T& value, OR& bytes)
{
// output format: RA_ICRS, DEC_ICRS, RA_APP, DEC_APP, HA, AZ, ZD, ALT, X, Y, pair-kind, time-point
// in the case of sexagesimal output X,Y coordinates will be interpretated
// according to value.pair_kind field
static constexpr char MccCoordinateXFmt = 'x';
static constexpr char MccCoordinateYFmt = 'y';
static constexpr char MccCoordinateRA_ICRSFmt = 'R';
static constexpr char MccCoordinateDEC_ICRSFmt = 'D';
static constexpr char MccCoordinateRA_APPFmt = 'r';
static constexpr char MccCoordinateDEC_APPFmt = 'd';
static constexpr char MccCoordinateHAFmt = 'h';
static constexpr char MccCoordinateAZFmt = 'a';
static constexpr char MccCoordinateZDFmt = 'z';
static constexpr char MccCoordinateALTFmt = 'A';
static constexpr char MccCoordinateTMFmt = 't'; // time point
static constexpr char MccCoordinatePKFmt = 'p'; // pair kind
if (_currentFormat == SerializedCoordFormat::CFMT_DEGREES) {
toDegrees(bytes, value.RA_ICRS, value.DEC_ICRS);
} else if (_currentFormat == SerializedCoordFormat::CFMT_SGM) {
toSexagesimalHour(bytes, value.RA_ICRS);
std::format_to(std::back_inserter(bytes), "{}", _delimiter);
toSexagesimalDeg(bytes, value.DEC_APP);
}
std::format_to(std::back_inserter(bytes), "{}", _delimiter);
MccEqtHrzCoordsSerializer{}(value, bytes);
}
};
class MccPointingTargetDeserializer : public MccCoordinateDeserializer
{
public:
template <traits::mcc_input_char_range IR, mcc_pointing_target_coord_c T>
std::error_code operator()(IR&& bytes, T& value)
{
// valid format: RA_ICRS, DEC_ICRS, RA_APP, DEC_APP, HA, AZ, ZD, ALT, X, Y, pair-kind, time-point
// in the case of sexagesimal input the X,Y coordinates will be interpretated
// according to value.pair_kind field
auto els = splitToElements(std::forward<IR>(bytes));
if (els.size() < 12) {
return std::make_error_code(std::errc::invalid_argument);
}
MccPointingTarget pt;
auto err = parseHourRepr(els[0], pt.RA_ICRS);
if (err) {
return err;
}
err = parseDegreeRepr(els[1], pt.DEC_ICRS);
if (err) {
return err;
}
err = MccEqtHrzCoordsDeserializer{}(std::string_view{els[2].begin(), els[11].end()}, pt);
if (err) {
return err;
}
mcc_copy_pointing_target_coord(pt, &value);
return {};
}
};
class MccTelemetryDataSerializer : public MccCoordinateSerializer
{
public:
template <mcc_telemetry_data_c T, traits::mcc_output_char_range OR>
void operator()(const T& value, OR& bytes)
{
// output format: <mount data>, speedX, speedY, pcmX, pcmY, refCorr, <target data>
MccEqtHrzCoordsSerializer{}(value, bytes);
std::format_to(std::back_inserter(bytes), "{}", _delimiter);
toDegrees(bytes, value.speedX, value.speedY, value.pcmX, value.pcmY, value.refCorr);
std::format_to(std::back_inserter(bytes), "{}", _delimiter);
MccPointingTargetSerializer{}(value.target, bytes);
}
};
class MccTelemetryDataDeserializer : public MccCoordinateDeserializer
{
public:
template <traits::mcc_input_char_range IR, mcc_telemetry_data_c T>
std::error_code operator()(IR&& bytes, T& value)
{
// valid format: <mount data>, speedX, speedY, pcmX, pcmY, refCorr, <target data>
auto els = splitToElements(std::forward<IR>(bytes));
if (els.size() < 12) {
return std::make_error_code(std::errc::invalid_argument);
}
MccTelemetryData tdata;
auto err = MccEqtHrzCoordsDeserializer{}(std::string_view{els[0].begin(), els[11].end()}, tdata);
if (err) {
return err;
}
err = parseDegreeRepr(els[5], tdata.speedX);
if (err) {
return err;
}
err = parseDegreeRepr(els[5], tdata.speedY);
if (err) {
return err;
}
err = parseDegreeRepr(els[5], tdata.pcmX);
if (err) {
return err;
}
err = parseDegreeRepr(els[5], tdata.pcmY);
if (err) {
return err;
}
err = parseDegreeRepr(els[5], tdata.refCorr);
if (err) {
return err;
}
err = MccPointingTargetDeserializer{}(std::string_view{els[0].begin(), els[11].end()}, tdata.target);
if (err) {
return err;
}
mcc_copy_telemetry_data(tdata, &value);
return {};
}
};
} // namespace mcc
template <mcc::mcc_celestial_point_c T>
struct std::formatter<T, char> {
std::vector<char> fmt_order;
template <typename ParseContext>
constexpr ParseContext::iterator parse(ParseContext& ctx)
{
bool do_fmt = false;
for (auto it = ctx.begin(); it != ctx.end(); ++it) {
if (*it == '%' && !do_fmt) {
do_fmt = true;
continue;
} else {
throw std::format_error("Invalid format argument for celestial point");
}
switch (*it) {
case mcc::MccCoordinateXFmt:
case mcc::MccCoordinateYFmt:
case mcc::MccCoordinateRA_ICRSFmt:
case mcc::MccCoordinateDEC_ICRSFmt:
case mcc::MccCoordinateRA_APPFmt:
case mcc::MccCoordinateDEC_APPFmt:
case mcc::MccCoordinateHAFmt:
case mcc::MccCoordinateAZFmt:
case mcc::MccCoordinateZDFmt:
case mcc::MccCoordinateALTFmt:
case mcc::MccCoordinateTMFmt:
case mcc::MccCoordinatePKFmt:
fmt_order.push_back(*it);
do_fmt = false;
break;
default:
throw std::format_error("Invalid format argument for celestial point");
}
}
}
template <typename FmtContext>
FmtContext::iterator format(mcc::mcc_celestial_point_c auto cp, FmtContext& ctx) const
{
std::ostringstream out;
if (fmt_order.empty()) {
return ctx.out();
}
for (auto& el : fmt_order) {
}
return std::ranges::copy(std::move(out).str(), ctx.out()).out;
}
};

View File

@ -70,6 +70,23 @@ int main()
std::cout << "\n\n\n";
mcc::MccCelestialPointSerializer cpser;
mcc::MccCelestialPointDeserializer cpdser;
std::string s;
cpser(cpt, s);
std::cout << "Serialized: " << s << "\n";
auto err = cpdser(s, cpt);
if (err) {
std::cout << "deserialization error: " << err.message() << "\n";
} else {
std::cout << "Deserialized: tp = " << cpt.time_point << "; kind = " << mcc::MccCoordPairKindToStr(cpt.pair_kind)
<< "\n";
}
std::cout << "\n\n\n";
mcc::MccCelestialCoordEpoch cep;
std::cout << "UTC: " << cep.UTC() << "\n";