/** * Determines whether point is within the object or on the surface * @param point :: Point to be tested * @returns true if point is within object or on surface */ bool MeshObject::isValid(const Kernel::V3D &point) const { BoundingBox bb = getBoundingBox(); if (!bb.isPointInside(point)) { return false; } Kernel::V3D direction(0.0, 0.0, 1.0); // direction to look for intersections std::vector<Kernel::V3D> intersectionPoints; std::vector<TrackDirection> entryExitFlags; getIntersections(point, direction, intersectionPoints, entryExitFlags); if (intersectionPoints.empty()) { return false; } // True if point is on surface for (const auto &intersectionPoint : intersectionPoints) { if (point.distance(intersectionPoint) < M_TOLERANCE) { return true; } } // Look for nearest point then check its entry-exit flag double nearestPointDistance = point.distance(intersectionPoints[0]); size_t nearestPointIndex = 0; for (size_t i = 1; i < intersectionPoints.size(); ++i) { if (point.distance(intersectionPoints[i]) < nearestPointDistance) { nearestPointDistance = point.distance(intersectionPoints[i]); nearestPointIndex = i; } } return (entryExitFlags[nearestPointIndex] == TrackDirection::LEAVING); }
/** * Returns selected information for a "peak" at QLabFrame. * * @param qFrame An arbitrary position in Q-space. This does not have to *be the * position of a peak. * @param labCoords Set true if the position is in the lab coordinate system, *false if * it is in the sample coordinate system. * @return a vector whose elements contain different information about the *"peak" at that position. * each element is a pair of description of information and the string *form for the corresponding * value. */ int PeaksWorkspace::peakInfoNumber(Kernel::V3D qFrame, bool labCoords) const { std::vector<std::pair<std::string, std::string>> Result; std::ostringstream oss; oss << std::setw(12) << std::fixed << std::setprecision(3) << (qFrame.norm()); std::pair<std::string, std::string> QMag("|Q|", oss.str()); Result.push_back(QMag); oss.str(""); oss.clear(); oss << std::setw(12) << std::fixed << std::setprecision(3) << (2.0 * M_PI / qFrame.norm()); std::pair<std::string, std::string> dspc("d-spacing", oss.str()); oss.str(""); oss.clear(); Result.push_back(dspc); int seqNum = -1; double minDist = 10000000; for (int i = 0; i < getNumberPeaks(); i++) { Peak pk = getPeak(i); V3D Q = pk.getQLabFrame(); if (!labCoords) Q = pk.getQSampleFrame(); double D = qFrame.distance(Q); if (D < minDist) { minDist = D; seqNum = i + 1; } } return seqNum; }
/** * Determines wither point is on the surface. * @param point :: Point to check * @returns true if the point is on the surface */ bool MeshObject::isOnSide(const Kernel::V3D &point) const { BoundingBox bb = getBoundingBox(); if (!bb.isPointInside(point)) { return false; } const std::vector<Kernel::V3D> directions = { Kernel::V3D{0, 0, 1}, Kernel::V3D{0, 1, 0}, Kernel::V3D{1, 0, 0}}; // directions to look for intersections // We have to look in several directions in case a point is on a face // or edge parallel to the first direction or also the second direction. for (const auto &direction : directions) { std::vector<Kernel::V3D> intersectionPoints; std::vector<TrackDirection> entryExitFlags; getIntersections(point, direction, intersectionPoints, entryExitFlags); if (intersectionPoints.empty()) { return false; } for (const auto &intersectionPoint : intersectionPoints) { if (point.distance(intersectionPoint) < M_TOLERANCE) { return true; } } } return false; }
int Line::lambdaPair( const int ix, const std::pair<std::complex<double>, std::complex<double>> &SQ, std::list<Kernel::V3D> &PntOut) const /** Helper function to decide which roots to take. The assumption is that lambda has been solved by quadratic equation and we require the points that correspond to these values. Note: have changed this so that only positive roots are returned. This makes the quadratic solutions consistent with the ones returned when asking if a line hits a plane. It is not clear if some other use cases exist. @param ix : number of solutions in SQ (0,1,2) @param SQ : solutions to lambda (the distance along the line @param PntOut : Output vector of points (added to) @return Number of real unique points found. */ { // check results if (ix < 1) return 0; int nCnt(0); // number of good points Kernel::V3D Ans; if (SQ.first.imag() == 0.0 && SQ.first.real() >= 0.0) // +ve roots only { const double lambda = SQ.first.real(); Kernel::V3D Ans = getPoint(lambda); PntOut.push_back(Ans); if (ix < 2) // only one unique root. return 1; nCnt = 1; } if (SQ.second.imag() == 0.0 && SQ.second.real() >= 0.0) // +ve roots only { const double lambda = SQ.second.real(); if (!nCnt) // first point wasn't good. { PntOut.push_back(getPoint(lambda)); return 1; } Kernel::V3D Ans2 = getPoint(lambda); // If points too close return only 1 item. if (Ans.distance(Ans2) < Tolerance) return 1; PntOut.push_back(Ans2); return 2; } return 0; // both point imaginary }
double Cylinder::distance(const Kernel::V3D &A) const /** Calculates the distance of point A from the surface of the cylinder. @param A :: Point to calculate distance from @return :: +ve distance to the surface. \todo INCOMPLETE AS Does not deal with the case of non axis centre line (has been updated?? ) */ { // First find the normal going to the point const Kernel::V3D Amov = A - Centre; double lambda = Amov.scalar_prod(Normal); const Kernel::V3D Ccut = Normal * lambda; // The distance is from the centre line to the return fabs(Ccut.distance(Amov) - Radius); }