/** Constructor helper method * @param min :: nd-sized vector of the minimum edge of the box in each * dimension * @param max :: nd-sized vector of the maximum edge of the box * */ void MDBoxImplicitFunction::construct(const Mantid::Kernel::VMD &min, const Mantid::Kernel::VMD &max) { size_t nd = min.size(); if (max.size() != nd) throw std::invalid_argument( "MDBoxImplicitFunction::ctor(): Min and max vector sizes must match!"); if (nd == 0 || nd > 100) throw std::invalid_argument( "MDBoxImplicitFunction::ctor(): Invalid number of dimensions!"); double volume = 1; for (size_t d = 0; d < nd; d++) { volume *= (max[d] - min[d]); // Make two parallel planes per dimension // Normal on the min side, so it faces towards +X std::vector<coord_t> normal_min(nd, 0); normal_min[d] = +1.0; // Origin just needs to have its X set to the value. Other coords are // irrelevant std::vector<coord_t> origin_min(nd, 0); origin_min[d] = static_cast<coord_t>(min[d]); // Build the plane MDPlane p_min(normal_min, origin_min); this->addPlane(p_min); // Normal on the max side, so it faces towards -X std::vector<coord_t> normal_max(nd, 0); normal_max[d] = -1.0; // Origin just needs to have its X set to the value. Other coords are // irrelevant std::vector<coord_t> origin_max(nd, 0); origin_max[d] = static_cast<coord_t>(max[d]); // Build the plane MDPlane p_max(normal_max, origin_max); this->addPlane(p_max); } m_volume = volume; }
/** Build a coordinate transformation based on an origin and orthogonal basis vectors. * This can reduce the number of dimensions. For example: * * - The input position is X=(x,y,z) * - The origin is X0=(x0,y0,z0) * - The basis vectors are U and V (reducing from 3 to 2D) * - The output position u = (X-X0).U = X.U - X0.U = x*Ux + y*Uy + z*Uz + (X0.U) * - The output position v = (X-X0).V = X.V - X0.V = x*Vx + y*Vy + z*Vz + (X0.V) * * And this allows us to create the affine matrix: * * | Ux Uy Uz X0.U | | x | | u | * | Vx Vy Vz X0.V | | y | = | v | * | 0 0 0 1 | | z | | 1 | * | 1 | * * @param origin :: origin (in the inDimension), which corresponds to (0,0,...) in outD * @param axes :: a list of basis vectors. There must be outD vectors (one for each output dimension) * and each vector must be of length inD (all coordinates in the input dimension). * The vectors must be properly orthogonal: not coplanar or collinear. This is not checked! * @param scaling :: a vector of size outD of the scaling to perform in each of the * OUTPUT dimensions. * @throw if inconsistent vector sizes are received, or zero-length */ void CoordTransformAffine::buildOrthogonal(const Mantid::Kernel::VMD & origin, const std::vector< Mantid::Kernel::VMD> & axes, const Mantid::Kernel::VMD & scaling) { if (origin.size() != inD) throw std::runtime_error("CoordTransformAffine::buildOrthogonal(): the origin must be in the dimensions of the input workspace (length inD)."); if (axes.size() != outD) throw std::runtime_error("CoordTransformAffine::buildOrthogonal(): you must give as many basis vectors as there are dimensions in the output workspace."); if (scaling.size() != outD) throw std::runtime_error("CoordTransformAffine::buildOrthogonal(): the size of the scaling vector must be the same as the number of dimensions in the output workspace."); // Start with identity affineMatrix.identityMatrix(); for (size_t i=0; i<axes.size(); i++) { if (axes[i].length() == 0.0) throw std::runtime_error("CoordTransformAffine::buildOrthogonal(): one of the basis vector was of zero length."); if (axes[i].size() != inD) throw std::runtime_error("CoordTransformAffine::buildOrthogonal(): one of the basis vectors had the wrong number of dimensions (must be inD)."); // Normalize each axis to unity VMD basis = axes[i]; basis.normalize(); // The row of the affine matrix = the unit vector for (size_t j=0; j<basis.size(); j++) affineMatrix[i][j] = basis[j] * scaling[i]; // Now account for the translation coord_t transl = 0; for (size_t j=0; j<basis.size(); j++) transl += origin[j] * basis[j]; // dot product of origin * basis aka ( X0 . U ) // The last column of the matrix = the translation movement affineMatrix[i][inD] = -transl * scaling[i]; } // Copy into the raw matrix (for speed) copyRawMatrix(); }