double RadiusSum::getMinBinSizeForInstrument(API::MatrixWorkspace_sptr inWS) { // Assumption made: the detectors are placed one after the other, so the // minimum // reasonalbe size for the bin is the width of one detector. double width; size_t i = 0; while (true) { i++; // this should never happen because it was done in // getBoundariesOfInstrument, // but it is here to avoid risk of infiniti loop if (i >= inWS->getNumberHistograms()) throw std::invalid_argument( "Did not find any non monitor detector position"); auto det = inWS->getDetector(i); if (det->isMonitor()) continue; Geometry::BoundingBox bbox; det->getBoundingBox(bbox); width = bbox.width().norm(); break; } return width; }
//! is the object visible? bool geometry::Camera::visible(const geometry::BoundingBox &bounds, const math::matrix4x4<float> &viewTransform) const { // perform test in view coordinates rather than word or screen space const int N = 8; int idx = 0; math::matrix4x1<float> points[N]; float w = bounds.width(), h = bounds.height(), d = bounds.depth(); points[0] = math::matrix4x1<float>(bounds.minimum, 1); points[++idx] = points[0] + math::matrix4x1<float>(w, 0, 0, 0); points[++idx] = points[0] + math::matrix4x1<float>(0, 0, d, 0); points[++idx] = points[0] + math::matrix4x1<float>(w, 0, d, 0); points[++idx] = points[0] + math::matrix4x1<float>(0, h, 0, 0); points[++idx] = points[0] + math::matrix4x1<float>(w, h, 0, 0); points[++idx] = points[0] + math::matrix4x1<float>(0, h, d, 0); points[++idx] = points[0] + math::matrix4x1<float>(w, h, d, 0); math::matrix3x1<float> normals[5]; float fovH = this->fovH(); float fovV = this->fovV(); normals[0] = math::matrix3x1<float>(std::sin(fovH/2.0f), 0, std::cos(fovH/2.0f)); normals[1] = math::matrix3x1<float>(-std::sin(fovH/2.0f), 0, std::cos(fovH/2.0f)); normals[2] = math::matrix3x1<float>(0, std::sin(fovV/2.0f), std::cos(fovV/2.0f)); normals[3] = math::matrix3x1<float>(0, -std::sin(fovV/2.0f), std::cos(fovV/2.0f)); normals[4] = math::matrix3x1<float>(0, 0, 1); bool allNegative[5] = { true }; for (int i = 0; i < N; i++) { points[i] = viewTransform * points[i]; for (int n = 0; n < 5 && allNegative[n]; n++) { if (points[i].dot(normals[n]) > 0) { allNegative[n] = false; } } } bool invisible = false; for (int n = 0; n < 5; n++) { invisible = invisible | allNegative[n]; } return !invisible; }
/** Loads the instrument into a workspace. */ void VesuvioL1ThetaResolution::calculateDetector( const IDetector &detector, std::function<double()> &flatRandomVariateGen, std::vector<double> &l1Values, std::vector<double> &thetaValues) { const int numEvents = getProperty("NumEvents"); l1Values.reserve(numEvents); thetaValues.reserve(numEvents); double sampleWidth = getProperty("SampleWidth"); // If the sample is large fix the width to the approximate beam width if (sampleWidth > 4.0) sampleWidth = 4.0; // Get detector dimensions Geometry::IObject_const_sptr pixelShape = detector.shape(); if (!pixelShape || !pixelShape->hasValidShape()) { throw std::invalid_argument("Detector pixel has no defined shape!"); } Geometry::BoundingBox detBounds = pixelShape->getBoundingBox(); V3D detBoxWidth = detBounds.width(); const double detWidth = detBoxWidth.X() * 100; const double detHeight = detBoxWidth.Y() * 100; g_log.debug() << "detWidth=" << detWidth << "\ndetHeight=" << detHeight << '\n'; // Scattering angle in rad const double theta = m_instWorkspace->detectorTwoTheta(detector); if (theta == 0.0) return; // Final flight path in cm const double l1av = detector.getDistance(*m_sample) * 100.0; const double x0 = l1av * sin(theta); const double y0 = l1av * cos(theta); // Get as many events as defined by NumEvents // This loop is not iteration limited but highly unlikely to ever become // infinate while (l1Values.size() < static_cast<size_t>(numEvents)) { const double xs = -sampleWidth / 2 + sampleWidth * flatRandomVariateGen(); const double ys = 0.0; const double zs = -sampleWidth / 2 + sampleWidth * flatRandomVariateGen(); const double rs = sqrt(pow(xs, 2) + pow(zs, 2)); if (rs <= sampleWidth / 2) { const double a = -detWidth / 2 + detWidth * flatRandomVariateGen(); const double xd = x0 - a * cos(theta); const double yd = y0 + a * sin(theta); const double zd = -detHeight / 2 + detHeight * flatRandomVariateGen(); const double l1 = sqrt(pow(xd - xs, 2) + pow(yd - ys, 2) + pow(zd - zs, 2)); double angle = acos(yd / l1); if (xd < 0.0) angle *= -1; // Convert angle to degrees angle *= 180.0 / M_PI; l1Values.push_back(l1); thetaValues.push_back(angle); } interruption_point(); } }