예제 #1
0
파일: RadiusSum.cpp 프로젝트: mcvine/mantid
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;
}
예제 #2
0
//! 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();
  }
}