/**
 * 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;
}
示例#2
0
/**
 * 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);
}
示例#3
0
std::string makeAxisName(const Kernel::V3D &Dir,
                         const std::vector<std::string> &QNames) {
  double eps(1.e-3);
  Kernel::V3D absDir(fabs(Dir.X()), fabs(Dir.Y()), fabs(Dir.Z()));
  std::string mainName;

  if ((absDir[0] >= absDir[1]) && (absDir[0] >= absDir[2])) {
    mainName = QNames[0];
  } else if (absDir[1] >= absDir[2]) {
    mainName = QNames[1];
  } else {
    mainName = QNames[2];
  }

  std::string name("["), separator = ",";
  for (size_t i = 0; i < 3; i++) {

    if (i == 2)
      separator = "]";
    if (absDir[i] < eps) {
      name += "0" + separator;
      continue;
    }
    if (Dir[i] < 0) {
      name += "-";
    }
    if (std::fabs(absDir[i] - 1) < eps) {
      name.append(mainName).append(separator);
      continue;
    }
    name.append(sprintfd(absDir[i], eps)).append(mainName).append(separator);
  }

  return name;
}
示例#4
0
/**
 * Return the XML for a sphere.
 */
std::string sphereXML(double radius, const Kernel::V3D &centre, const std::string &id) {
    std::ostringstream xml;
    xml << "<sphere id=\"" << id << "\">"
        << "<centre x=\"" << centre.X() << "\"  y=\"" << centre.Y() << "\" z=\""
        << centre.Z() << "\" />"
        << "<radius val=\"" << radius << "\" />"
        << "</sphere>";
    return xml.str();
}
示例#5
0
文件: Cone.cpp 项目: stothe2/mantid
/**
 Calculate if the point R is on
 the cone (Note: have to be careful here
 since angle calcuation calcuates an angle.
 We need a distance for tolerance!)
 @param R :: Point to check
 @return 1 if on surface and 0 if not not on surface
 */
int Cone::onSurface(const Kernel::V3D &R) const {

    const Kernel::V3D cR = R - Centre;
    double rptAngle = cR.scalar_prod(Normal);
    rptAngle *= rptAngle / cR.scalar_prod(cR);
    const double eqn(sqrt(rptAngle));

    return (fabs(eqn - cangle) > Tolerance) ? 0 : 1;
}
/**
 * Set the new detector position given the r,theta and phi.
 * @param detectorInfo :: Reference to the DetectorInfo
 * @param index :: Index into detectorInfo
 * @param l2 :: A single l2
 * @param theta :: A single theta
 * @param phi :: A single phi
 */
void UpdateInstrumentFromFile::setDetectorPosition(
    Geometry::DetectorInfo &detectorInfo, const size_t index, const float l2,
    const float theta, const float phi) {
  if (m_ignoreMonitors && detectorInfo.isMonitor(index))
    return;

  Kernel::V3D pos;
  pos.spherical(l2, theta, phi);
  detectorInfo.setPosition(index, pos);
}
示例#7
0
文件: Cone.cpp 项目: stothe2/mantid
/**
 Calculate if the point R is within
 the cone (return -1) or outside,
 (return 1)
 \todo NEEDS ON SURFACE CALCULATING::
 waiting for a point to cone distance function

 @param R :: Point to determine if in/out of cone
 @return Side of R
 */
int Cone::side(const Kernel::V3D &R) const {

    const Kernel::V3D cR = R - Centre;
    double rptAngle = cR.scalar_prod(Normal);
    rptAngle *= rptAngle / cR.scalar_prod(cR);
    const double eqn(sqrt(rptAngle));
    if (fabs(eqn - cangle) < Tolerance)
        return 0;
    return (eqn > cangle) ? 1 : -1;
}
示例#8
0
/// Returns 2 theta (scattering angle w.r.t. to beam direction).
double DetectorInfo::twoTheta(const size_t index) const {
  const Kernel::V3D samplePos = samplePosition();
  const Kernel::V3D beamLine = samplePos - sourcePosition();

  if (beamLine.nullVector()) {
    throw Kernel::Exception::InstrumentDefinitionError(
        "Source and sample are at same position!");
  }

  return getDetector(index).getTwoTheta(samplePos, beamLine);
}
示例#9
0
double Line::distance(const Kernel::V3D &A) const
/**
Distance of a point from the line
@param A :: test Point
@return absolute distance (not signed)
*/
{
    const double lambda = Direct.scalar_prod(A - Origin);
    Kernel::V3D L = getPoint(lambda);
    L -= A;
    return L.norm();
}
示例#10
0
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
}
示例#11
0
/**
 * Estalish if points are coplanar.
 * @param vertices : All vertices to consider
 * @return : Return True only if all coplanar
 */
bool MeshObject2D::pointsCoplanar(const std::vector<Kernel::V3D> &vertices) {
  if (!CoplanarChecks::sufficientPoints(vertices))
    return false;

  Kernel::V3D normal = CoplanarChecks::surfaceNormal(vertices);
  // Check that a valid normal was found amongst collection of vertices
  if (normal.norm2() == 0) {
    // If all points are colinear. Not a plane.
    return false;
  }

  return CoplanarChecks::allCoplanar(vertices, normal);
}
示例#12
0
/// Returns signed 2 theta (signed scattering angle w.r.t. to beam direction).
double DetectorInfo::signedTwoTheta(const size_t index) const {
  const Kernel::V3D samplePos = samplePosition();
  const Kernel::V3D beamLine = samplePos - sourcePosition();

  if (beamLine.nullVector()) {
    throw Kernel::Exception::InstrumentDefinitionError(
        "Source and sample are at same position!");
  }
  // Get the instrument up axis.
  const Kernel::V3D &instrumentUpAxis =
      m_instrument->getReferenceFrame()->vecPointingUp();
  return getDetector(index)
      .getSignedTwoTheta(samplePos, beamLine, instrumentUpAxis);
}
示例#13
0
/**
 * Find maximum angular half width of the bounding box from the observer, that
 * is
 * the greatest angle between the centre point and any corner point
 * @param observer :: Viewing point
 * @returns The value of the angular half-width
*/
double BoundingBox::angularWidth(const Kernel::V3D &observer) const {
  Kernel::V3D centre = centrePoint() - observer;
  std::vector<Kernel::V3D> pts;
  this->getFullBox(pts, observer);

  std::vector<Kernel::V3D>::const_iterator ip;
  double centre_norm_inv = 1.0 / centre.norm();
  double thetaMax(-1.0);
  for (ip = pts.begin(); ip != pts.end(); ++ip) {
    double theta = acos(ip->scalar_prod(centre) * centre_norm_inv / ip->norm());
    if (theta > thetaMax)
      thetaMax = theta;
  }
  return thetaMax;
}
示例#14
0
/**
 * 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;
}
示例#15
0
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);
}
    /**
     * Set the new detector position given the r,theta and phi.
     * @param det :: A pointer to the detector
     * @param l2 :: A single l2
     * @param theta :: A single theta
     * @param phi :: A single phi
     */
    void UpdateInstrumentFromFile::setDetectorPosition(const Geometry::IDetector_const_sptr & det, const float l2,
                                                       const float theta, const float phi)
    {
      if( m_ignoreMonitors && det->isMonitor() ) return;

      Geometry::ParameterMap & pmap = m_workspace->instrumentParameters();
      Kernel::V3D pos;
      if (!m_ignorePhi)
      {
        pos.spherical(l2, theta, phi);
      }
      else
      {
        double r,t,p;
        det->getPos().getSpherical(r,t,p);
        pos.spherical(l2, theta, p);
      }
      Geometry::ComponentHelper::moveComponent(*det, pmap, pos, Geometry::ComponentHelper::Absolute);
    }
示例#17
0
std::pair<double, double> LoadILLSANS::calculateQMaxQMin() {
  double min = std::numeric_limits<double>::max(),
         max = std::numeric_limits<double>::min();
  g_log.debug("Calculating Qmin Qmax...");
  std::size_t nHist = m_localWorkspace->getNumberHistograms();
  for (std::size_t i = 0; i < nHist; ++i) {
    Geometry::IDetector_const_sptr det = m_localWorkspace->getDetector(i);
    if (!det->isMonitor()) {
      const MantidVec &lambdaBinning = m_localWorkspace->readX(i);
      Kernel::V3D detPos = det->getPos();
      double r, theta, phi;
      detPos.getSpherical(r, theta, phi);
      double v1 = calculateQ(*(lambdaBinning.begin()), theta);
      double v2 = calculateQ(*(lambdaBinning.end() - 1), theta);
      // std::cout << "i=" << i << " theta="<<theta << " lambda_i=" <<
      // *(lambdaBinning.begin()) << " lambda_f=" << *(lambdaBinning.end()-1) <<
      // " v1=" << v1 << " v2=" << v2 << '\n';
      if (i == 0) {
        min = v1;
        max = v1;
      }
      if (v1 < min) {
        min = v1;
      }
      if (v2 < min) {
        min = v2;
      }
      if (v1 > max) {
        max = v1;
      }
      if (v2 > max) {
        max = v2;
      }
    } else
      g_log.debug() << "Detector " << i << " is a Monitor : " << det->getID()
                    << '\n';
  }

  g_log.debug() << "Calculating Qmin Qmax. Done : [" << min << "," << max
                << "]\n";

  return std::pair<double, double>(min, max);
}
示例#18
0
double
Torus::distance(const Kernel::V3D& Pt) const
  /**
    Calculates the distance from the point to the Torus
    does not calculate the point on the Torusthat is closest
    @param Pt :: Point to calcuate from

    - normalise to a cone vertex at the origin
    - calculate the angle between the axis and the Point
    - Calculate the distance to P
    @return distance to Pt
  */
{
  const Kernel::V3D Px=Pt-Centre;
  // test is the centre to point distance is zero
  if(Px.norm()<Tolerance)
    return Px.norm();
  return Px.norm();
}
示例#19
0
double Plane::distance(const Kernel::V3D &A) const
/**
  Determine the distance of point A from the plane
  returns a value relative to the normal
  @param A :: point to get distance from
  @return singed distance from point
*/
{
  return A.scalar_prod(NormV) - Dist;
}
示例#20
0
int Line::intersect(std::list<Kernel::V3D> &PntOut, const Cylinder &Cyl) const
/**
For the line that intersects the cylinder generate
add the point to the VecOut, return number of points
added. It does not check the points for validity.

@param PntOut :: Vector of points found by the line/cylinder intersection
@param Cyl :: Cylinder to intersect line with
@return Number of points found by intersection
*/
{
    const Kernel::V3D Cent = Cyl.getCentre();
    const Kernel::V3D Ax = Origin - Cent;
    const Kernel::V3D N = Cyl.getNormal();
    const double R = Cyl.getRadius();
    const double vDn = N.scalar_prod(Direct);
    const double vDA = N.scalar_prod(Ax);
    // First solve the equation of intersection
    double C[3];
    C[0] = 1.0 - (vDn * vDn);
    C[1] = 2.0 * (Ax.scalar_prod(Direct) - vDA * vDn);
    C[2] = Ax.scalar_prod(Ax) - (R * R + vDA * vDA);
    std::pair<std::complex<double>, std::complex<double>> SQ;
    const int ix = solveQuadratic(C, SQ);
    // This takes the centre displacement into account:
    return lambdaPair(ix, SQ, PntOut);
}
示例#21
0
文件: Cone.cpp 项目: trnielsen/mantid
    double Cone::distance(const Kernel::V3D& Pt) const
    /**
     Calculates the distance from the point to the Cone
     does not calculate the point on the cone that is closest
     @param Pt :: Point to calcuate from

     - normalise to a cone vertex at the origin
     - calculate the angle between the axis and the Point
     - Calculate the distance to P
     @return distance to Pt
     */
    {
      const Kernel::V3D Px = Pt - Centre;
      // test is the centre to point distance is zero
      if (Px.norm() < Tolerance)
        return Px.norm();
      double Pangle = Px.scalar_prod(Normal) / Px.norm();
      if (Pangle < 0.0)
        Pangle = acos(-Pangle);
      else
        Pangle = acos(Pangle);

      Pangle -= M_PI * alpha / 180.0;
      return Px.norm() * sin(Pangle);
    }
示例#22
0
/**
 * This function calculates the exponential contribution to the He3 tube
 * efficiency.
 * @param spectraIndex :: the current index to calculate
 * @param idet :: the current detector pointer
 * @throw out_of_range if twice tube thickness is greater than tube diameter
 * @return the exponential contribution for the given detector
 */
double He3TubeEfficiency::calculateExponential(
    std::size_t spectraIndex,
    boost::shared_ptr<const Geometry::IDetector> idet) {
  // Get the parameters for the current associated tube
  double pressure =
      this->getParameter("TubePressure", spectraIndex, "tube_pressure", idet);
  double tubethickness =
      this->getParameter("TubeThickness", spectraIndex, "tube_thickness", idet);
  double temperature = this->getParameter("TubeTemperature", spectraIndex,
                                          "tube_temperature", idet);

  double detRadius(0.0);
  Kernel::V3D detAxis;
  this->getDetectorGeometry(idet, detRadius, detAxis);
  double detDiameter = 2.0 * detRadius;
  double twiceTubeThickness = 2.0 * tubethickness;

  // now get the sin of the angle, it's the magnitude of the cross product of
  // unit vector along the detector tube axis and a unit vector directed from
  // the sample to the detector center
  Kernel::V3D vectorFromSample = idet->getPos() - this->samplePos;
  vectorFromSample.normalize();
  Kernel::Quat rot = idet->getRotation();
  // rotate the original cylinder object axis to get the detector axis in the
  // actual instrument
  rot.rotate(detAxis);
  detAxis.normalize();
  // Scalar product is quicker than cross product
  double cosTheta = detAxis.scalar_prod(vectorFromSample);
  double sinTheta = std::sqrt(1.0 - cosTheta * cosTheta);

  const double straight_path = detDiameter - twiceTubeThickness;
  if (std::fabs(straight_path - 0.0) < TOL) {
    throw std::out_of_range("Twice tube thickness cannot be greater than "
                            "or equal to the tube diameter");
  }

  const double pathlength = straight_path / sinTheta;
  return EXP_SCALAR_CONST * (pressure / temperature) * pathlength;
}
示例#23
0
文件: Cone.cpp 项目: stothe2/mantid
void Cone::setNorm(const Kernel::V3D &A)
/**
 Sets the Normal and the Base Equation
 @param A :: New Normal direction
 */
{
    if (A.norm() > Tolerance) {
        Normal = A;
        Normal.normalize();
        setBaseEqn();
    }
    return;
}
示例#24
0
int Line::intersect(std::list<Kernel::V3D> &PntOut, const Sphere &Sph) const
/**
For the line that intersects the cylinder generate
add the point to the VecOut, return number of points
added. It does not check the points for validity.

@param PntOut :: Vector of points found by the line/sphere intersection
@param Sph :: Sphere to intersect line with
@return Number of points found by intersection
*/
{
    // Nasty stripping of useful stuff from sphere
    const Kernel::V3D Ax = Origin - Sph.getCentre();
    const double R = Sph.getRadius();
    // First solve the equation of intersection
    double C[3];
    C[0] = 1;
    C[1] = 2.0 * Ax.scalar_prod(Direct);
    C[2] = Ax.scalar_prod(Ax) - R * R;
    std::pair<std::complex<double>, std::complex<double>> SQ;
    const int ix = solveQuadratic(C, SQ);
    return lambdaPair(ix, SQ, PntOut);
}
示例#25
0
/**
 * Calculate volume.
 * @return The volume.
 */
double MeshObject::volume() const {
  // Select centre of bounding box as centre point.
  // For each triangle calculate the signed volume of
  // the tetrahedron formed by the triangle and the
  // centre point. Then add to total.

  BoundingBox bb = getBoundingBox();
  double cX = 0.5 * (bb.xMax() + bb.xMin());
  double cY = 0.5 * (bb.yMax() + bb.yMin());
  double cZ = 0.5 * (bb.zMax() + bb.zMin());
  Kernel::V3D centre(cX, cY, cZ);

  double volumeTimesSix(0.0);

  Kernel::V3D vertex1, vertex2, vertex3;
  for (size_t i = 0; getTriangle(i, vertex1, vertex2, vertex3); ++i) {
    Kernel::V3D a = vertex1 - centre;
    Kernel::V3D b = vertex2 - centre;
    Kernel::V3D c = vertex3 - centre;
    volumeTimesSix += a.scalar_prod(b.cross_prod(c));
  }

  return volumeTimesSix / 6.0;
}
示例#26
0
int Line::setLine(const Kernel::V3D &O, const Kernel::V3D &D)
/**
sets the line given the Origne and direction
@param O :: origin
@param D :: direction
@retval  0 ::  Direction == 0 ie no line
@retval 1 :: on success
*/
{
    if (D.nullVector())
        return 0;
    Origin = O;
    Direct = D;
    Direct.normalize();
    return 1;
}
示例#27
0
int Plane::setPlane(const Kernel::V3D &P, const Kernel::V3D &N)
/**
  Given a point and a normal direction set the plane
  @param P :: Point for plane to pass thought
  @param N :: Normal for the plane
  @retval 0 :: success
*/
{
  try {
    NormV = normalize(N);
  } catch (std::runtime_error &) {
    throw std::invalid_argument("Attempt to create Plane with zero normal");
  }
  Dist = P.scalar_prod(NormV);
  setBaseEqn();
  return 0;
}
示例#28
0
/**
 * Returns whether the given reflection is allowed or not in this space group
 *
 * Space groups that contain translational symmetry cause certain reflections
 * to be absent due to the contributions of symmetry equivalent atoms to the
 * structure factor cancelling out. This method implements the procedure
 * described in ITA [1] to check whether a reflection is allowed or not
 * according to the symmetry operations in the space group. Please note that
 * certain arrangements of atoms can lead to additional conditions that can not
 * be determined using a space group's symmetry operations alone. For these
 * situations, Geometry::CrystalStructure can help.
 *
 * [1] International Tables for Crystallography (2006). Vol. A, ch. 12.3, p. 832
 *
 * @param hkl :: HKL to be checked.
 * @return :: true if the reflection is allowed, false otherwise.
 */
bool SpaceGroup::isAllowedReflection(const Kernel::V3D &hkl) const {
  for (const auto &operation : m_allOperations) {
    if (operation.hasTranslation()) {
      /* Floating point precision problem:
       *    (H . v) % 1.0 is not always exactly 0, so instead:
       *    | [(H . v) + delta] % 1.0 | > 1e-14 is checked
       * The transformation is only performed if necessary.
       */
      if ((fabs(fmod(fabs(hkl.scalar_prod(operation.reducedVector())) + 1e-15,
                     1.0)) > 1e-14) &&
          (operation.transformHKL(hkl) == hkl)) {
        return false;
      }
    }
  }

  return true;
}
示例#29
0
/**
 * Establish if all vertices are coplanar
 * @param vertices : All vertices to check
 * @param normal : Surface normal
 * @return True only if all vertices are coplanar
 */
bool allCoplanar(const std::vector<Kernel::V3D> &vertices,
                 const Kernel::V3D &normal) {
  bool in_plane = true;
  auto v0 = vertices[0];
  const auto nx = normal[0];
  const auto ny = normal[1];
  const auto nz = normal[2];
  const auto k = nx * v0.X() + ny * v0.Y() + nz * v0.Z();
  const auto denom = normal.norm();
  const static double tolerance =
      1e-9; // Fixed Tolerance. Too expensive to calculate
            // based on machine uncertaintly for each
            // vertex.

  for (const auto &vertex : vertices) {
    auto d = (nx * vertex.X() + ny * vertex.Y() + nz * vertex.Z() - k) / denom;
    if (d > tolerance || d < -1 * tolerance) {
      in_plane = false;
      break;
    }
  }
  return in_plane;
}
示例#30
0
/**
 * Return a local point in a cylinder shape
 *
 * @param basis a basis vector
 * @param alongAxis symmetry axis vector of a cylinder
 * @param polarAngle a polar angle (in radians) of a point in a cylinder
 * @param radialLength radial position of point in a cylinder
 * @return a local point inside the cylinder
 */
Kernel::V3D localPointInCylinder(const Kernel::V3D &basis,
                                 const Kernel::V3D &alongAxis,
                                 double polarAngle, double radialLength) {
  // Use basis to get a second perpendicular vector to define basis2
  Kernel::V3D basis2;
  if (basis.X() == 0) {
    basis2.setX(1.);
  } else if (basis.Y() == 0) {
    basis2.setY(1.);
  } else if (basis.Z() == 0) {
    basis2.setZ(1.);
  } else {
    basis2.setX(-basis.Y());
    basis2.setY(basis.X());
    basis2.normalize();
  }
  const Kernel::V3D basis3{basis.cross_prod(basis2)};
  const Kernel::V3D localPoint{
      ((basis2 * std::cos(polarAngle) + basis3 * std::sin(polarAngle)) *
       radialLength) +
      alongAxis};
  return localPoint;
}