diff --git a/Device/Detector/Detector2D.cpp b/Device/Detector/Detector2D.cpp index acab1a51f9bcae65b44824f9d32adde202eee734..cc20d54044f5056ee320ed959c1914f49c7f4c9a 100644 --- a/Device/Detector/Detector2D.cpp +++ b/Device/Detector/Detector2D.cpp @@ -23,33 +23,48 @@ namespace { -Scale* scatteringAngles(const std::string& label, size_t n, double angle_min, double angle_max) +//! Returns true scattering angles for given nominal scale. +//! The nominal scale is an equidistant partition of the interval between true minimum and +//! maximum scattering angle. It is used for the graphical representation of detector pixels. +//! The true scattering angle is used for the computation of scattering towards a detector pixel. +Scale* scatteringAngles(const Scale& in) { + const size_t n = in.size(); ASSERT(n > 0); - const double p0 = tan(angle_min); - const double dp = (tan(angle_max) - tan(angle_min)) / n; + const double p0 = tan(in.min()); + const double dp = (tan(in.max()) - tan(in.min())) / n; std::vector<double> limits; limits.reserve(2 * n); - limits.push_back(angle_min); + limits.push_back(in.min()); for (size_t i = 1; i < n; ++i) { limits.push_back(atan(p0 + i * dp)); limits.push_back(atan(p0 + i * dp)); } - limits.push_back(angle_max); - return newGenericScale(label, limits); + limits.push_back(in.max()); + return newGenericScale(in.axisLabel(), limits); } } // namespace +Detector2D::Detector2D(Frame* frame) + : IDetector(frame) + , m_scattering_phi(::scatteringAngles(frame->xAxis())) + , m_scattering_alpha(::scatteringAngles(frame->yAxis())) +{ +} + Detector2D::Detector2D(size_t n_phi, double phi_min, double phi_max, size_t n_alpha, double alpha_min, double alpha_max) - : IDetector(new Frame(::scatteringAngles("phi_f (rad)", n_phi, phi_min, phi_max), - ::scatteringAngles("alpha_f (rad)", n_alpha, alpha_min, alpha_max))) + : Detector2D(new Frame(newEquiDivision("phi_f (rad)", n_phi, phi_min, phi_max), + newEquiDivision("alpha_f (rad)", n_alpha, alpha_min, alpha_max))) { } -Detector2D::Detector2D(const Detector2D& other) = default; +Detector2D::Detector2D(const Detector2D& other) + : Detector2D(other.frame().clone()) +{ +} Detector2D* Detector2D::clone() const { @@ -58,13 +73,11 @@ Detector2D* Detector2D::clone() const IPixel* Detector2D::createPixel(size_t index) const { - const Scale& phi_axis = axis(0); - const Scale& alpha_axis = axis(1); const size_t phi_index = axisBinIndex(index, 0); const size_t alpha_index = axisBinIndex(index, 1); - const Bin1D alpha_bin = alpha_axis.bin(alpha_index); - const Bin1D phi_bin = phi_axis.bin(phi_index); + const Bin1D alpha_bin = m_scattering_alpha->bin(alpha_index); + const Bin1D phi_bin = m_scattering_phi->bin(phi_index); return new SphericalPixel(alpha_bin, phi_bin); } @@ -72,9 +85,8 @@ size_t Detector2D::indexOfSpecular(const Beam& beam) const { double alpha = beam.alpha_i(); double phi = beam.phi_i(); - const Scale& phi_axis = axis(0); - const Scale& alpha_axis = axis(1); - if (phi_axis.rangeComprises(phi) && alpha_axis.rangeComprises(alpha)) - return getGlobalIndex(phi_axis.closestIndex(phi), alpha_axis.closestIndex(alpha)); + if (m_scattering_phi->rangeComprises(phi) && m_scattering_alpha->rangeComprises(alpha)) + return getGlobalIndex(m_scattering_phi->closestIndex(phi), + m_scattering_alpha->closestIndex(alpha)); return totalSize(); } diff --git a/Device/Detector/Detector2D.h b/Device/Detector/Detector2D.h index a7d07272699a3e82490c3cfd6b99ba15e87bb5f4..f7ecec2b93f362b443cf29d8e5612749e5234b2f 100644 --- a/Device/Detector/Detector2D.h +++ b/Device/Detector/Detector2D.h @@ -40,6 +40,12 @@ public: //! If no pixel contains this specular wavevector, the number of pixels is //! returned. This corresponds to an overflow index. size_t indexOfSpecular(const Beam& beam) const override; + +private: + Detector2D(Frame* frame); + + std::unique_ptr<Scale> m_scattering_phi; + std::unique_ptr<Scale> m_scattering_alpha; }; #endif // BORNAGAIN_DEVICE_DETECTOR_DETECTOR2D_H