From 40d36545f3b5f43b6835920c5d34358bef33600e Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 18 Mar 2026 19:00:23 +0300 Subject: [PATCH] ... --- include/mcc/mcc_pcm.h | 10 ++- include/mcc/mcc_pcm_construct.h | 126 ++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 include/mcc/mcc_pcm_construct.h diff --git a/include/mcc/mcc_pcm.h b/include/mcc/mcc_pcm.h index 70a606e..2dcd2c7 100644 --- a/include/mcc/mcc_pcm.h +++ b/include/mcc/mcc_pcm.h @@ -2,9 +2,15 @@ #pragma once -/* MOUNT CONTROL COMPONENTS LIBRARY */ +/**************************************************************************************** + * * + * MOUNT CONTROL COMPONENTS LIBRARY * + * * + * * + * A REFERENCE "POINTING-CORRECTION-MODEL" CLASS IMPLEMENTATION * + * * + ****************************************************************************************/ -/* A REFERENCE "POINTING-CORRECTION-MODEL" CLASS IMPLEMENTATION */ #include diff --git a/include/mcc/mcc_pcm_construct.h b/include/mcc/mcc_pcm_construct.h new file mode 100644 index 0000000..e9cec93 --- /dev/null +++ b/include/mcc/mcc_pcm_construct.h @@ -0,0 +1,126 @@ +#pragma once + +/**************************************************************************************** + * * + * MOUNT CONTROL COMPONENTS LIBRARY * + * * + * * + * "POINTING-CORRECTION-MODEL" FITTER * + * * + ****************************************************************************************/ + +#include + +#include "mcc_concepts.h" +#include "mcc_coordinate.h" +#include "mcc_pcm.h" + +namespace mcc::impl +{ + +template +class MccPcmRefPointTable +{ +public: + using ref_coordpair_t = std::conditional_t, + MccSkyHADEC_OBS, + std::conditional_t, MccSkyAZZD, void>>; + + static_assert(!std::is_void_v, "UNSUPPORTED MOUNT TYPE!"); + + struct table_elem_t { + double target_colon, target_colat; + double hw_colon, hw_colat; + double colon_res, colat_res; // target - hw + }; + + MccError addPoint(mcc_skypoint_c auto target_coords, + mcc_coord_pair_c auto const& hw_counts, + mcc_coord_epoch_c auto const& ref_epoch) + requires(decltype(hw_counts)::pairKind == MccCoordPairKind::COORDS_KIND_XY) + { + auto err = target_coords.to(ref_coordpair_t::pairKind, ref_epoch); + if (err) { + return mcc_deduced_err(err, MccDefaultPCMErrorCode::ERROR_CCTE); + } + + _table.push_back({target_coords.co_lon(), target_coords.co_lat(), hw_counts.x(), hw_counts.y(), + target_coords.co_lon() - hw_counts.x(), target_coords.co_lat() - hw_counts.y()}); + + return {}; + } + + + MccError addPoint(mcc_skypoint_c auto target_coords, mcc_coord_pair_c auto const& hw_counts) + { + auto ref_epoch = hw_counts.epoch(); + + return addPoint(std::move(target_coords), hw_counts, ref_epoch); + } + + + // + // for B-splines interior knots along axes must be given in 'pcm_data' + // NOTE: the size of the interior knots array must be at least 2 as + // it are interpretated as border knots and final full knots set is: + // knots = [input_knots[0], input_knots[0], input_knots[0], input_knots[0], input_knots[1], input_knots[2], + // ..., input_knots[N-1], input_knots[N-1], input_knots[N-1], input_knots[N-1]], where N = input_knots.size() + // + // WARNING: the input knots for inverse B-spline are ignored so the direct and inverse B-spline coefficients are + // calculated on the same mesh! + MccError computeModel(MccDefaultPCM::pcm_data_t& pcm_data) + { + size_t min_data_size = 2; // 2 is for BSPLINE + + if (pcm_data.type == MccDefaultPCMType::PCM_TYPE_GEOMETRY) { + if constexpr (MOUNT_TYPE == MccMountType::FORK_TYPE) { + min_data_size = 9; + } else { + min_data_size = 8; + } + + if (_table.size() < min_data_size) { + // return error + } + } + + +#ifdef USE_BSPLINE_PCM + if (pcm_data.bspline.knotsX.size() < 2 || pcm_data.bspline.knotsY.size() < 2) { + // TODO: return error + } + + std::vector tx(pcm_data.bspline.knotsX.size() + 6), ty(pcm_data.bspline.knotsY.size() + 6); + + size_t Ncoeffs = (tx.size() - 4) * (ty.size() - 4); + + pcm_data.bspline.coeffsX.resize(Ncoeffs); + pcm_data.bspline.coeffsY.resize(Ncoeffs); + + if (pcm_data.type == MccDefaultPCMType::PCM_TYPE_BSPLINE) { + if (_table.size() < min_data_size) { + // return error + } + + pcm_data.inverseBspline.coeffsX.resize(Ncoeffs); + pcm_data.inverseBspline.coeffsY.resize(Ncoeffs); + + } else if (pcm_data.type == MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE) { + // the fitting for geometrical coefficients is already done above so + // one must fit residuals by bivariate B-splines + + std::vector xres(_table.size()), yres(_table.size()); + for (size_t i = 0; i < _table.size(); ++i) { + xres = _table[i].target_colon; + yres = _table[i].target_colat; + } + } + } +#endif + +protected: + std::vector _table; +}; + + +} // namespace mcc::impl \ No newline at end of file