31#include <boost/accumulators/accumulators.hpp>
32#include <boost/accumulators/statistics/error_of_mean.hpp>
33#include <boost/accumulators/statistics/mean.hpp>
34#include <boost/accumulators/statistics/stats.hpp>
41#include <unordered_set>
50constexpr double VALID_INTERCEPT_POINT_SHIFT{2.5e-05};
64double triangleSolidAngle(
const V3D &a,
const V3D &b,
const V3D &c,
const V3D &observer) {
65 const V3D ao = a - observer;
66 const V3D bo = b - observer;
67 const V3D co = c - observer;
68 const double modao = ao.
norm();
69 const double modbo = bo.
norm();
70 const double modco = co.
norm();
75 const double denom = modao * modbo * modco + modco * aobo + modbo * aoco + modao * boco;
77 return 2.0 * atan2(scalTripProd, denom);
101 constexpr V3D initial_axis(0., 0., 1.0);
102 const Quat transform(initial_axis, axis_direction);
107 std::array<double, Mantid::Geometry::Cone::g_NSLICES> cos_table;
108 std::array<double, Mantid::Geometry::Cone::g_NSLICES> sin_table;
110 double solid_angle(0.0);
113 cos_table[vertex] = std::cos(angle_step * vertex);
114 sin_table[vertex] = std::sin(angle_step * vertex);
119 cos_table[vertex] = std::cos(angle_step * vertex);
120 sin_table[vertex] = std::sin(angle_step * vertex);
126 transform.rotate(pt2);
127 transform.rotate(pt3);
131 double sa = triangleSolidAngle(centre, pt2, pt3, observer);
140 double z0(0.0), z1(z_step);
141 double r0(
radius), r1(r0 - r_step);
146 V3D pt1 =
V3D(r0 * cos_table[vertex], r0 * sin_table[vertex], z0);
151 V3D pt3 =
V3D(r0 * cos_table[vertex], r0 * sin_table[vertex], z0);
154 V3D pt2 =
V3D(r1 * cos_table[vertex], r1 * sin_table[vertex], z1);
159 V3D pt4 =
V3D(r1 * cos_table[vertex], r1 * sin_table[vertex], z1);
161 transform.rotate(pt1);
162 transform.rotate(pt3);
163 transform.rotate(pt2);
164 transform.rotate(pt4);
170 double sa = triangleSolidAngle(pt1, pt4, pt3, observer);
174 sa = triangleSolidAngle(pt1, pt2, pt4, observer);
188 transform.
rotate(top_centre);
189 top_centre += centre;
193 V3D pt2 =
V3D(r0 * cos_table[vertex], r0 * sin_table[vertex],
height);
199 V3D pt3 =
V3D(r0 * cos_table[vertex], r0 * sin_table[vertex],
height);
202 transform.rotate(pt2);
203 transform.rotate(pt3);
208 double sa = triangleSolidAngle(top_centre, pt3, pt2, observer);
225double cuboidSolidAngle(
const V3D &observer,
const std::vector<V3D> &vectors) {
230 std::vector<V3D> pts;
232 const V3D dx = vectors[1] - vectors[0];
233 const V3D dz = vectors[3] - vectors[0];
234 pts.emplace_back(vectors[2]);
235 pts.emplace_back(vectors[2] + dx);
236 pts.emplace_back(vectors[1]);
237 pts.emplace_back(vectors[0]);
238 pts.emplace_back(vectors[2] + dz);
239 pts.emplace_back(vectors[2] + dz + dx);
240 pts.emplace_back(vectors[1] + dz);
241 pts.emplace_back(vectors[0] + dz);
243 constexpr unsigned int ntriangles(12);
244 std::vector<std::vector<int>> triMap(ntriangles, std::vector<int>(3, 0));
282 for (
unsigned int i = 0; i < ntriangles; i++) {
283 const double sa = triangleSolidAngle(pts[triMap[i][0] - 1], pts[triMap[i][1] - 1], pts[triMap[i][2] - 1], observer);
300double cylinderSolidAngle(
const V3D &observer,
const V3D ¢re,
const V3D &axis,
const double radius,
310 constexpr V3D initial_axis(0., 0., 1.0);
311 const Quat transform(initial_axis, axis);
317 double z0(0.0), z1(z_step);
318 double solid_angle(0.0);
324 double x =
radius * std::cos(angle_step * sl);
325 double y =
radius * std::sin(angle_step * sl);
329 x =
radius * std::cos(angle_step * vertex);
330 y =
radius * std::sin(angle_step * vertex);
334 transform.rotate(pt1);
335 transform.rotate(pt3);
336 transform.rotate(pt2);
337 transform.rotate(pt4);
344 double sa = triangleSolidAngle(pt1, pt4, pt3, observer);
348 sa = triangleSolidAngle(pt1, pt2, pt4, observer);
368double sphereSolidAngle(
const V3D &observer,
const std::vector<V3D> &vectors,
const double radius) {
369 const double distance = (observer - vectors[0]).norm();
370 if (distance >
radius + Tolerance) {
371 const double sa = 2.0 * M_PI * (1.0 - cos(asin(
radius / distance)));
373 }
else if (distance <
radius - Tolerance)
395 : m_topRule(nullptr), m_boundingBox(), AABBxMax(0), AABByMax(0), AABBzMax(0), AABBxMin(0), AABByMin(0), AABBzMin(0),
396 boolBounded(false), m_objNum(0), m_handler(
std::make_shared<
GeometryHandler>(this)), bGeometryCaching(false),
469 static const boost::regex letters(
"[a-zA-Z]");
504 std::string::size_type pos = TopStr.find(
'#');
505 std::ostringstream cx;
506 while (pos != std::string::npos) {
508 cx << TopStr.substr(0, pos);
513 auto vc = MList.find(cN);
514 if (vc == MList.end())
518 cx << vc->second.cellStr(MList);
522 TopStr.erase(0, pos);
523 pos = TopStr.find(
'#');
539 std::string::size_type posA = lineStr.find(
"#(");
541 if (posA == std::string::npos)
547 std::string::size_type posB;
548 posB = lineStr.find_first_of(
"()", posA);
549 if (posB == std::string::npos)
550 throw std::runtime_error(
"Object::complement :: " + lineStr);
552 numBrackets = (lineStr[posB] ==
'(') ? 1 : 0;
553 while (posB != std::string::npos && numBrackets) {
554 posB = lineStr.find_first_of(
"()", posB);
555 if (posB == std::string::npos)
557 numBrackets += (lineStr[posB] ==
'(') ? 1 : -1;
561 std::string Part = lineStr.substr(posA, posB - (posA + 1));
566 lineStr.erase(posA - 1, posB + 1);
567 std::ostringstream CompCell;
568 CompCell << cellNum <<
" ";
569 lineStr.insert(posA - 1, CompCell.str());
573 throw std::runtime_error(
"Object::complement :: " + Part);
596 std::deque<Rule *> rules;
598 while (!rules.empty()) {
599 Rule *T1 = rules.front();
603 auto *surface =
dynamic_cast<SurfPoint *
>(T1);
606 auto mapFound = surfMap.find(surface->getKeyN());
607 if (mapFound != surfMap.end()) {
608 surface->
setKey(mapFound->second);
618 rules.emplace_back(TA);
620 rules.emplace_back(TB);
639int CSGObject::procPair(std::string &lineStr, std::map<
int, std::unique_ptr<Rule>> &ruleMap,
int &compUnit)
const
646 for (Rstart = 0; Rstart < lineStr.size() && lineStr[Rstart] !=
'R'; Rstart++)
653 ruleMap.find(Ra) == ruleMap.end())
656 for (Rend = Rstart + 1; Rend < lineStr.size() && lineStr[Rend] !=
'R'; Rend++) {
657 if (lineStr[Rend] ==
':')
661 ruleMap.find(Rb) == ruleMap.end()) {
667 for (Rend++; Rend < lineStr.size() && lineStr[Rend] >=
'0' && lineStr[Rend] <=
'9'; Rend++)
672 (type) ? std::unique_ptr<Rule>(std::make_unique<Union>(std::move(ruleMap[Ra]), std::move(ruleMap[Rb])))
673 : std::unique_ptr<Rule>(std::make_unique<Intersection>(std::move(ruleMap[Ra]), std::move(ruleMap[Rb])));
674 ruleMap[Ra] = std::move(Join);
675 ruleMap.erase(ruleMap.find(Rb));
679 for (strPos = Rstart - 1; strPos >= 0 && lineStr[strPos] ==
' '; strPos--)
681 Rstart = (strPos < 0) ? 0 : strPos;
682 for (strPos = Rend; strPos < static_cast<int>(lineStr.size()) && lineStr[strPos] ==
' '; strPos++)
686 std::stringstream newRuleStr;
687 newRuleStr <<
" R" << Ra <<
" ";
688 lineStr.replace(Rstart, Rend, newRuleStr.str());
700 return std::make_unique<CompGrp>();
703 Rule *RItemptr = ruleItem.get();
704 auto CG = std::make_unique<CompGrp>(Pptr, std::move(ruleItem));
706 const int Ln = Pptr->
findLeaf(RItemptr);
707 Pptr->
setLeaf(std::move(CG), Ln);
709 return std::make_unique<CompGrp>();
733 std::vector<Kernel::V3D> Snorms;
737 if ((*vc)->onSurface(point)) {
738 Snorms.emplace_back((*vc)->surfaceNormal(point));
746 for (
auto xs = Snorms.begin(); xs != Snorms.end(); ++xs)
747 for (
auto ys = std::next(xs); ys != Snorms.end(); ++ys) {
748 NormPair = (*ys) + (*xs);
753 }
catch (std::runtime_error &) {
809 std::stack<const Rule *> TreeLine;
811 while (!TreeLine.empty()) {
812 const Rule *tmpA = TreeLine.top();
822 const auto *SurX =
dynamic_cast<const SurfPoint *
>(tmpA);
829 std::unordered_set<const Surface *> uniqueSurfacePtrs;
832 if (uniqueSurfacePtrs.find(sPtr) != std::end(uniqueSurfacePtrs)) {
835 uniqueSurfacePtrs.insert(sPtr);
839 m_surList.erase(newEnd, m_surList.end());
843 std::vector<const Surface *>::const_iterator vc;
844 for (vc = m_surList.begin(); vc != m_surList.end(); ++vc) {
845 logger.debug() <<
"Point == " << *vc <<
'\n';
846 logger.debug() << (*vc)->getName() <<
'\n';
857 std::vector<int> out;
858 transform(
m_surList.begin(),
m_surList.end(), std::insert_iterator<std::vector<int>>(out, out.begin()),
889 const int out =
m_topRule->substituteSurf(surfNum, newSurfNum, surfPtr);
899 std::deque<Rule *> rst;
900 std::vector<int> Cells;
905 while (!rst.empty()) {
906 Rule *T1 = rst.front();
910 auto *surface =
dynamic_cast<SurfPoint *
>(T1);
912 Cells.emplace_back(surface->getKeyN());
917 rst.emplace_back(TA);
919 rst.emplace_back(TB);
924 logger.debug() <<
"Name == " <<
m_objNum <<
'\n';
925 logger.debug() <<
"Rules == " << Rcount <<
'\n';
926 std::vector<int>::const_iterator mc;
927 logger.debug() <<
"Surface included == ";
928 for (mc = Cells.begin(); mc < Cells.end(); ++mc) {
929 logger.debug() << (*mc) <<
" ";
931 logger.debug() <<
'\n';
946 logger.debug() <<
"Name == " <<
m_objNum <<
'\n';
947 logger.debug() <<
m_topRule->display() <<
'\n';
956 std::ostringstream objStr;
968 std::ostringstream objStr;
982 std::ostringstream objStr;
983 objStr.precision(10);
996 std::map<int, std::unique_ptr<Rule>> RuleList;
1000 std::unique_ptr<SurfPoint> TmpR;
1001 std::unique_ptr<CompObj> TmpO;
1003 std::string Ln = lineStr;
1005 std::ostringstream cx;
1006 const std::string::size_type length = Ln.length();
1007 for (
size_t i = 0; i < length; i++) {
1008 if (isdigit(Ln[i]) || Ln[i] ==
'-') {
1012 throw std::invalid_argument(
"Invalid surface string in Object::ProcString : " + lineStr);
1014 if (i != 0 && Ln[i - 1] ==
'#') {
1015 TmpO = std::make_unique<CompObj>();
1017 RuleList[Ridx] = std::move(TmpO);
1020 TmpR = std::make_unique<SurfPoint>();
1022 RuleList[Ridx] = std::move(TmpR);
1024 cx <<
" R" << Ridx <<
" ";
1034 int brack_exists = 1;
1035 while (brack_exists) {
1036 std::string::size_type rbrack = Ln.find(
')');
1037 std::string::size_type lbrack = Ln.rfind(
'(', rbrack);
1038 if (rbrack != std::string::npos && lbrack != std::string::npos) {
1039 std::string Lx = Ln.substr(lbrack + 1, rbrack - lbrack - 1);
1042 while (
procPair(Lx, RuleList, compUnit))
1044 Ln.replace(lbrack, 1 + rbrack - lbrack, Lx);
1047 for (hCnt =
static_cast<int>(lbrack) - 1; hCnt >= 0 && isspace(Ln[hCnt]); hCnt--)
1049 if (hCnt >= 0 && Ln[hCnt] ==
'#') {
1050 RuleList[compUnit] =
procComp(std::move(RuleList[compUnit]));
1051 Ln.erase(hCnt, lbrack - hCnt);
1058 while (
procPair(Ln, RuleList, nullInt)) {
1061 if (RuleList.size() == 1) {
1062 m_topRule = std::move((RuleList.begin())->second);
1064 throw std::logic_error(
"Object::procString() - Unexpected number of "
1065 "surface rules found. Expected=1, found=" +
1078 int originalCount = track.
count();
1085 surface->acceptVisitor(LI);
1098 const size_t nPoints(IPoints.size());
1101 for (
size_t i = 0; i < nPoints; i++) {
1107 const auto ¤tPt(IPoints[i]);
1108 const auto &prePt((i == 0 || dPoints[i - 1] <= 0) ? track.
startPoint() : IPoints[i - 1]);
1109 const auto &nextPt(i + 1 < nPoints ? IPoints[i + 1] : currentPt + currentPt - prePt);
1115 track.
addPoint(trackType, currentPt, *
this);
1121 return (track.
count() - originalCount);
1133 surface->acceptVisitor(LI);
1137 if (!distances.empty()) {
1138 return std::abs(*std::min_element(std::begin(distances), std::end(distances)));
1140 std::ostringstream os;
1141 os <<
"Unable to find intersection with object with track starting at " << track.
startPoint() <<
" in direction "
1143 throw std::runtime_error(os.str());
1159 const Kernel::V3D shift(uVec * VALID_INTERCEPT_POINT_SHIFT);
1160 const int flagA =
isValid(point - shift);
1161 const int flagB =
isValid(point + shift);
1162 if (!(flagA ^ flagB))
1179 const auto upstreamPt = (prePt + curPt) * 0.5;
1180 const auto upstreamPtInsideShape =
isValid(upstreamPt);
1182 const auto downstreamPt = (curPt + nxtPt) * 0.5;
1183 const auto downstreamPtInsideShape =
isValid(downstreamPt);
1201 if (!(upstreamPtInsideShape ^ downstreamPtInsideShape))
1250 const int resNoBB = 200, resPhiMin = 10;
1251 int res = resNoBB, itheta, jphi, resPhi;
1252 double theta, phi, sum, dphi, dtheta;
1259 double thetaMax = M_PI;
1260 bool useBB =
false, usePt =
false;
1266 useBB = usePt =
true;
1269 const int resBB = 100;
1279 ptInObject -= observer;
1280 double theta0 = -180.0 / M_PI * acos(ptInObject.
Z() / ptInObject.
norm());
1285 zToPt(theta0, axis);
1287 dtheta = thetaMax / res;
1288 int count = 0, countPhi;
1290 for (itheta = 1; itheta <= res; itheta++) {
1292 theta = thetaMax * (itheta - 0.5) / res;
1293 resPhi =
static_cast<int>(res * sin(theta));
1294 if (resPhi < resPhiMin)
1296 dphi = 2 * M_PI / resPhi;
1298 for (jphi = 1; jphi <= resPhi; jphi++) {
1300 phi = 2.0 * M_PI * (jphi - 0.5) / resPhi;
1301 Kernel::V3D dir(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
1305 Track tr(observer, dir);
1307 sum += dtheta * dphi * sin(theta);
1314 if (!useBB && countPhi == 0)
1318 if (!useBB &&
count < resPhiMin + 1) {
1321 thetaMax = thetaMax * (itheta - 0.5) / res;
1322 dtheta = thetaMax / res;
1324 for (itheta = 1; itheta <= res; itheta++) {
1325 theta = thetaMax * (itheta - 0.5) / res;
1326 resPhi =
static_cast<int>(res * sin(theta));
1327 if (resPhi < resPhiMin)
1329 dphi = 2 * M_PI / resPhi;
1331 for (jphi = 1; jphi <= resPhi; jphi++) {
1332 phi = 2.0 * M_PI * (jphi - 0.5) / resPhi;
1333 Kernel::V3D dir(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
1336 Track tr(observer, dir);
1338 sum += dtheta * dphi * sin(theta);
1367 return (2.0 * M_PI);
1369 return (4.0 * M_PI);
1376 std::vector<Mantid::Kernel::V3D> geometry_vectors;
1378 geometry_vectors.reserve(4);
1384 return cuboidSolidAngle(observer, geometry_vectors);
1387 return sphereSolidAngle(observer, geometry_vectors,
radius);
1390 return cylinderSolidAngle(observer, geometry_vectors[0], geometry_vectors[1],
radius,
height);
1393 return coneSolidAngle(observer, geometry_vectors[0], geometry_vectors[1],
radius,
height);
1402 double sangle(0.0), sneg(0.0);
1403 for (
size_t i = 0; i < nTri; i++) {
1404 int p1 = faces[i * 3], p2 = faces[i * 3 + 1], p3 = faces[i * 3 + 2];
1405 V3D vp1 =
V3D(vertices[3 * p1], vertices[3 * p1 + 1], vertices[3 * p1 + 2]);
1406 V3D vp2 =
V3D(vertices[3 * p2], vertices[3 * p2 + 1], vertices[3 * p2 + 2]);
1407 V3D vp3 =
V3D(vertices[3 * p3], vertices[3 * p3 + 1], vertices[3 * p3 + 2]);
1408 double sa = triangleSolidAngle(vp1, vp2, vp3, observer);
1427 return 0.5 * (sangle - sneg);
1448 double sx = scaleFactor[0], sy = scaleFactor[1], sz = scaleFactor[2];
1449 const V3D sObserver = observer;
1453 return (2.0 * M_PI);
1455 return (4.0 * M_PI);
1468 std::vector<Kernel::V3D> vectors;
1472 std::transform(vectors.begin(), vectors.end(), vectors.begin(),
1473 [scaleFactor](
const V3D &v) { return v * scaleFactor; });
1474 return cuboidSolidAngle(observer, vectors);
1477 return sphereSolidAngle(observer, vectors,
radius);
1490 double sangle(0.0), sneg(0.0);
1491 for (
size_t i = 0; i < nTri; i++) {
1492 int p1 = faces[i * 3], p2 = faces[i * 3 + 1], p3 = faces[i * 3 + 2];
1495 V3D vp1 =
V3D(sx * vertices[3 * p1], sy * vertices[3 * p1 + 1], sz * vertices[3 * p1 + 2]);
1496 V3D vp2 =
V3D(sx * vertices[3 * p2], sy * vertices[3 * p2 + 1], sz * vertices[3 * p2 + 2]);
1497 V3D vp3 =
V3D(sx * vertices[3 * p3], sy * vertices[3 * p3 + 1], sz * vertices[3 * p3 + 2]);
1498 double sa = triangleSolidAngle(vp1, vp2, vp3, observer);
1504 return (0.5 * (sangle - sneg));
1517 std::vector<Kernel::V3D> vectors;
1569 using namespace boost::accumulators;
1570 const int singleShotIterations = 10000;
1571 accumulator_set<double, features<tag::mean, tag::error_of<tag::mean>>> accumulate;
1573 std::ranlux48 rnEngine;
1575 for (
int i = 0; i < 10; ++i) {
1576 const auto seed = rnEngine();
1580 const double relativeErrorTolerance = 1e-3;
1582 double currentError;
1584 const auto seed = rnEngine();
1587 currentMean = mean(accumulate);
1588 currentError = error_of<tag::mean>(accumulate);
1589 if (std::isnan(currentError)) {
1592 }
while (currentError / currentMean > relativeErrorTolerance);
1604 if (boundingBox.isNull()) {
1605 throw std::runtime_error(
"Cannot calculate volume: invalid bounding box.");
1608 const double boundingDx = boundingBox.xMax() - boundingBox.xMin();
1609 const double boundingDy = boundingBox.yMax() - boundingBox.yMin();
1610 const double boundingDz = boundingBox.zMax() - boundingBox.zMin();
1614 size_t blocksize = shotSize / threadCount;
1616 if (currentThreadNum == threadCount - 1) {
1619 blocksize = shotSize - (threadCount - 1) * blocksize;
1621 std::mt19937 rnEngine(
static_cast<std::mt19937::result_type
>(seed));
1627 rnEngine.discard(currentThreadNum * 3 * blocksize);
1628 std::uniform_real_distribution<double> rnDistribution(0.0, 1.0);
1630 for (
int i = 0; i < static_cast<int>(blocksize); ++i) {
1631 double rnd = rnDistribution(rnEngine);
1632 const double x = boundingBox.xMin() + rnd * boundingDx;
1633 rnd = rnDistribution(rnEngine);
1634 const double y = boundingBox.yMin() + rnd * boundingDy;
1635 rnd = rnDistribution(rnEngine);
1636 const double z = boundingBox.zMin() + rnd * boundingDz;
1645 const double ratio =
static_cast<double>(totalHits) /
static_cast<double>(shotSize);
1646 const double boundingVolume = boundingDx * boundingDy * boundingDz;
1647 return ratio * boundingVolume;
1707 const double huge(1e10);
1708 const double big(1e4);
1709 double minX(-huge), minY(-huge), minZ(-huge);
1710 double maxX(huge), maxY(huge), maxZ(huge);
1713 m_topRule->getBoundingBox(maxX, maxY, maxZ, minX, minY, minZ);
1717 if (minX > -big && maxX < big && minY > -big && maxY < big && minZ > -big && maxZ < big && minX <= maxX &&
1718 minY <= maxY && minZ <= maxZ) {
1736 if (vertCount > 0) {
1739 constexpr double huge = 1e10;
1740 double minX, maxX, minY, maxY, minZ, maxZ;
1741 minX = minY = minZ = huge;
1742 maxX = maxY = maxZ = -huge;
1745 for (
size_t i = 0; i < vertCount; ++i) {
1746 auto vx = vertArray[3 * i + 0];
1747 auto vy = vertArray[3 * i + 1];
1748 auto vz = vertArray[3 * i + 2];
1750 minX = std::min(minX, vx);
1751 maxX = std::max(maxX, vx);
1752 minY = std::min(minY, vy);
1753 maxY = std::max(maxY, vy);
1754 minZ = std::min(minZ, vz);
1755 maxZ = std::max(maxZ, vz);
1775 double minX, maxX, minY, maxY, minZ, maxZ;
1779 std::vector<Kernel::V3D> vectors;
1790 auto &lfb = vectors[0];
1791 auto &lft = vectors[1];
1792 auto &lbb = vectors[2];
1793 auto &rfb = vectors[3];
1796 auto lbt = lft + (lbb - lfb);
1797 auto rft = rfb + (lft - lfb);
1798 auto rbb = lbb + (rfb - lfb);
1799 auto rbt = rbb + (rft - rfb);
1801 vectors.emplace_back(lbt);
1802 vectors.emplace_back(rft);
1803 vectors.emplace_back(rbb);
1804 vectors.emplace_back(rbt);
1807 constexpr double huge = 1e10;
1808 minX = minY = minZ = huge;
1809 maxX = maxY = maxZ = -huge;
1812 for (
const auto &vector : vectors) {
1813 minX = std::min(minX, vector.X());
1814 maxX = std::max(maxX, vector.X());
1815 minY = std::min(minY, vector.Y());
1816 maxY = std::max(maxY, vector.Y());
1817 minZ = std::min(minZ, vector.Z());
1818 maxZ = std::max(maxZ, vector.Z());
1823 minX = minY = minZ = std::numeric_limits<
decltype(minZ)>::max();
1824 maxX = maxY = maxZ = -std::numeric_limits<
decltype(maxZ)>::max();
1827 for (
const auto &vector : vectors) {
1828 minX = std::min(minX, vector.X());
1829 maxX = std::max(maxX, vector.X());
1830 minY = std::min(minY, vector.Y());
1831 maxY = std::max(maxY, vector.Y());
1832 minZ = std::min(minZ, vector.Z());
1833 maxZ = std::max(maxZ, vector.Z());
1838 auto &base = vectors[0];
1839 auto &axis = vectors[1];
1845 volatile auto rx =
radius * sqrt(pow(axis.
Y(), 2) + pow(axis.
Z(), 2));
1846 volatile auto ry =
radius * sqrt(pow(axis.
X(), 2) + pow(axis.
Z(), 2));
1847 volatile auto rz =
radius * sqrt(pow(axis.
X(), 2) + pow(axis.
Y(), 2));
1851 minX = std::min(base.X(),
top.X()) - rx;
1852 maxX = std::max(base.X(),
top.X()) + rx;
1853 minY = std::min(base.Y(),
top.Y()) - ry;
1854 maxY = std::max(base.Y(),
top.Y()) + ry;
1855 minZ = std::min(base.Z(),
top.Z()) - rz;
1856 maxZ = std::max(base.Z(),
top.Z()) + rz;
1860 auto &tip = vectors[0];
1861 auto &axis = vectors[1];
1862 auto base = tip + (axis *
height);
1867 auto rx =
radius * sqrt(pow(axis.
Y(), 2) + pow(axis.
Z(), 2));
1868 auto ry =
radius * sqrt(pow(axis.
X(), 2) + pow(axis.
Z(), 2));
1869 auto rz =
radius * sqrt(pow(axis.
X(), 2) + pow(axis.
Y(), 2));
1872 minX = std::min(tip.X(), base.X() - rx);
1873 maxX = std::max(tip.X(), base.X() + rx);
1874 minY = std::min(tip.Y(), base.Y() - ry);
1875 maxY = std::max(tip.Y(), base.Y() + ry);
1876 minZ = std::min(tip.Z(), base.Z() - rz);
1877 maxZ = std::max(tip.Z(), base.Z() + rz);
1901 double &zmin)
const {
1903 xmax = ymax = zmax = xmin = ymin = zmin = 0.0;
1914 if (
AABBxMax >= xmax || AABBxMin <= xmin || AABByMax >= ymax || AABByMin <= ymin || AABBzMax >= zmax ||
1943 const double &yMin,
const double &zMin) {
2002 const size_t maxAttempts)
const {
2003 boost::optional<V3D> point{boost::none};
2011 const size_t bruteForceAttempts{std::min(
static_cast<size_t>(5), maxAttempts)};
2049 const size_t maxAttempts)
const {
2050 boost::optional<V3D> point{boost::none};
2057 const size_t bruteForceAttempts{std::min(
static_cast<size_t>(5), maxAttempts)};
2061 std::vector<Kernel::V3D> shapeVectors;
2068 point = RandomPoint::bounded<RandomPoint::inCuboid>(
m_handler->shapeInfo(), rng, activeRegion,
2069 maxAttempts - bruteForceAttempts);
2072 point = RandomPoint::bounded<RandomPoint::inCylinder>(
m_handler->shapeInfo(), rng, activeRegion,
2073 maxAttempts - bruteForceAttempts);
2076 point = RandomPoint::bounded<RandomPoint::inHollowCylinder>(
m_handler->shapeInfo(), rng, activeRegion,
2077 maxAttempts - bruteForceAttempts);
2080 point = RandomPoint::bounded<RandomPoint::inSphere>(
m_handler->shapeInfo(), rng, activeRegion,
2081 maxAttempts - bruteForceAttempts);
2103 for (
const auto &dir :
2104 {
V3D(1., 0., 0.),
V3D(-1., 0., 0.),
V3D(0., 1., 0.),
V3D(0., -1., 0.),
V3D(0., 0., 1.),
V3D(0., 0., -1.)}) {
2107 point = tr.
cbegin()->entryPoint;
2208 static const std::vector<double> empty;
2211 return m_handler->getTriangleVertices();
2218 static const std::vector<uint32_t> empty;
2236 throw std::logic_error(
"CSGObject has no ShapeInfo to return");
#define PARALLEL_THREAD_NUMBER
#define PARALLEL_CRITICAL(name)
#define PARALLEL_NUMBER_OF_THREADS
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
bool isPointInside(const Kernel::V3D &point) const
Is the given point within the bounding box?
double angularWidth(const Kernel::V3D &observer) const
Calculate the angular half width from the given point.
bool isNonNull() const
Is the box considered valid. Convenience for !isNull()
bool doesLineIntersect(const Track &track) const
Does a specified track intersect the bounding box.
static void checkValid(double xmax, double ymax, double zmax, double xmin, double ymin, double zmin)
Do the given arguments form a valid bounding box, throws std::invalid argument if not.
Kernel::V3D centrePoint() const
Returns the centre of the bounding box.
Constructive Solid Geometry object.
void setVtkGeometryCacheWriter(std::shared_ptr< vtkGeometryCacheWriter >)
set vtkGeometryCache writer
int m_objNum
Creation number.
std::shared_ptr< vtkGeometryCacheReader > vtkCacheReader
a pointer to a class for reading from the geometry cache
std::string cellCompStr() const
Write the object to a string.
std::string m_shapeXML
original shape xml used to generate this object.
bool isValid(const Kernel::V3D &) const override
Check if a point is valid.
void makeComplement()
Takes the complement of a group.
void updateGeometryHandler()
Updates the geometry handler if needed.
void GetObjectGeom(detail::ShapeInfo::GeometryShape &type, std::vector< Kernel::V3D > &vectors, double &innerRadius, double &radius, double &height) const override
get info on standard shapes
int createSurfaceList(const int outFlag=0)
create Surface list
int setObject(const int objName, const std::string &lineStr)
Object line == cell.
void setGeometryHandler(const std::shared_ptr< GeometryHandler > &h)
Set Geometry Handler.
int checkSurfaceValid(const Kernel::V3D &, const Kernel::V3D &) const
Determine if a point is valid by checking both directions of the normal away from the line A good poi...
double AABByMin
xmin of Axis aligned bounding box cache
const BoundingBox & getBoundingBox() const override
Return cached value of axis-aligned bounding box.
const Kernel::Material & material() const override
std::string cellStr(const std::map< int, CSGObject > &) const
Returns just the cell string object.
std::vector< const Surface * > m_surList
Full surfaces (make a map.
int substituteSurf(const int surfNum, const int newSurfNum, const std::shared_ptr< Surface > &surfPtr)
Removes a surface and then re-builds the cell.
double AABBzMin
zmin of Axis Aligned Bounding Box Cache
double volume() const override
Calculates the volume of this object.
int getPointInObject(Kernel::V3D &point) const override
Try to find a point that lies within (or on) the object.
const std::vector< uint32_t > & getTriangleFaces() const
for solid angle from triangulation
int removeSurface(const int surfNum)
Removes a surface and then re-builds the cell.
~CSGObject() override
Destructor.
std::unique_ptr< CompGrp > procComp(std::unique_ptr< Rule >) const
Takes a Rule item and makes it a complementary group.
void write(std::ostream &) const
MCNPX output.
int procPair(std::string &lineStr, std::map< int, std::unique_ptr< Rule > > &ruleMap, int &compUnit) const
This takes a string lineStr, finds the first two Rxxx function, determines their join type make the r...
double singleShotMonteCarloVolume(const int shotSize, const size_t seed) const
Returns the volume.
void convertComplement(const std::map< int, CSGObject > &)
Returns just the cell string object.
const std::vector< double > & getTriangleVertices() const
get vertices
std::string m_id
Optional string identifier.
std::unique_ptr< Kernel::Material > m_material
material composition
size_t numberOfTriangles() const
void setNullBoundingBox()
Set a null bounding box for this object.
std::string getShapeXML() const
Getter for the shape xml.
void setMaterial(const Kernel::Material &material) override
int searchForObject(Kernel::V3D &) const
Try to find a point that lies within (or on) the object, given a seed point.
double solidAngle(const Kernel::V3D &observer) const override
Find solid angle of object wrt the observer.
double rayTraceSolidAngle(const Kernel::V3D &observer) const
Given an observer position find the approximate solid angle of the object.
std::shared_ptr< GeometryHandler > getGeometryHandler() const override
Returns the geometry handler.
void draw() const override
Draws the Object using geometry handler, If the handler is not set then this function does nothing.
double AABBzMax
zmax of Axis aligned bounding box cache
int complementaryObject(const int cellNum, std::string &lineStr)
Process a complementary object.
CSGObject & operator=(const CSGObject &)
Assignment operator.
double AABBxMin
xmin of Axis aligned bounding box cache
std::shared_ptr< GeometryHandler > m_handler
Geometry Handle for rendering.
virtual void print() const
Prints almost everything.
double distance(const Track &track) const override
Compute the distance to the first point of intersection with the surface.
const Rule * topRule() const
Return the top rule.
double AABByMax
ymax of Axis aligned bounding box cache
void calcBoundingBoxByRule()
Calculate bounding box using Rule system.
bool bGeometryCaching
Is geometry caching enabled?
CSGObject()
Default constructor.
std::string str() const
Write the object to a string.
double monteCarloVolume() const
Returns the volume.
std::vector< int > getSurfaceIndex() const
Returns all of the numbers of surfaces.
Mantid::Geometry::TrackDirection calcValidTypeBy3Points(const Kernel::V3D &prePt, const Kernel::V3D &curPt, const Kernel::V3D &nxtPt) const
Check if an intercept is guiding the ray into the shape or leaving the shape.
void initDraw() const override
Initializes/prepares the object to be rendered, this will generate geometry for object,...
bool hasValidShape() const override
Return whether this object has a valid shape.
std::shared_ptr< vtkGeometryCacheWriter > vtkCacheWriter
a pointer to a class for writing to the geometry cache
int hasComplement() const
Determine if the object has a complementary object.
double AABBxMax
xmax of Axis aligned bounding box cache
BoundingBox m_boundingBox
Object's bounding box.
const detail::ShapeInfo & shapeInfo() const override
Mantid::Geometry::TrackDirection calcValidType(const Kernel::V3D &Pt, const Kernel::V3D &uVec) const
Calculate if a point PT is a valid point on the track.
bool boolBounded
flag true if a bounding box exists, either by
bool isOnSide(const Kernel::V3D &) const override
void calcBoundingBoxByVertices()
Calculate bounding box using object's vertices.
int procString(const std::string &lineStr)
Processes the cell string.
detail::ShapeInfo::GeometryShape shape() const override
size_t numberOfVertices() const
void printTree() const
Displays the rule tree.
std::unique_ptr< Rule > m_topRule
Top rule [ Geometric scope of object].
int populate(const std::map< int, std::shared_ptr< Surface > > &)
Goes through the cell objects and adds the pointers to the SurfPoint keys (using their keyN)
int interceptSurface(Geometry::Track &track) const override
Given a track, fill the track with valid section.
void setVtkGeometryCacheReader(std::shared_ptr< vtkGeometryCacheReader >)
set vtkGeometryCache reader
void defineBoundingBox(const double &xMax, const double &yMax, const double &zMax, const double &xMin, const double &yMin, const double &zMin)
Define axis-aligned bounding box.
boost::optional< Kernel::V3D > generatePointInObject(Kernel::PseudoRandomNumberGenerator &rng, const size_t) const override
Select a random point within the object.
double triangulatedSolidAngle(const Kernel::V3D &observer) const
Find solid angle of object from point "observer" using the OC triangulation of the object,...
void calcBoundingBoxByGeometry()
Calculate bounding box using object's geometric data.
static constexpr int g_NSLICES
The number of slices to approximate a cone.
static constexpr int g_NSTACKS
The number of stacks to approximate a cone.
static constexpr int g_NSTACKS
The number of stacks to approximate a cylinder.
static constexpr int g_NSLICES
The number of slices to approximate a cylinder.
Handles rendering of all object Geometry.
Interset of Line with a surface.
const Line::PType & getPoints() const
Get the intersection points.
const DistancesType & getDistance() const
Get the distance.
void sortAndRemoveDuplicates()
Prune out duplicated points and sort by distance to starting point.
Object generation rule tree.
Rule * getParent() const
Returns the parent object.
virtual Rule * leaf(const int=0) const
No leaf for a base rule.
virtual int findLeaf(const Rule *) const =0
Abstract find.
virtual void setLeaf(std::unique_ptr< Rule >, const int=0)=0
Abstract set.
static int removeItem(std::unique_ptr< Rule > &TRule, const int SurfN)
Given an item as a surface name, remove the surface from the Rule tree.
virtual std::string display() const =0
Abstract Display.
void setKey(const std::shared_ptr< Surface > &Spoint)
Sets the key pointer.
Holds a basic quadratic surface.
int getName() const
Get Name.
Defines a track as a start point and a direction.
const Kernel::V3D & startPoint() const
Returns the starting point.
void addPoint(const TrackDirection direction, const Kernel::V3D &endPoint, const IObject &obj, const ComponentID compID=nullptr)
Adds a point of intersection to the track.
void buildLink()
Construct links between added points.
int count() const
Returns the number of links.
const Kernel::V3D & direction() const
Returns the direction as a unit vector.
LType::const_iterator cbegin() const
Returns an interator to the start of the set of links (const version)
@ HOLLOWCYLINDER
HOLLOW CYLINDER.
Reads the Geometry Cache from the file to the Object.
Writes the Geometry from Object to Cache.
Exception for when an item is not found in a collection.
The Logger class is in charge of the publishing messages from the framework through various channels.
A material is defined as being composed of a given element, defined as a PhysicalConstants::NeutronAt...
Defines a 1D pseudo-random number generator, i.e.
void rotate(V3D &) const
Rotate a vector.
constexpr double scalar_prod(const V3D &v) const noexcept
Calculates the cross product.
constexpr double X() const noexcept
Get x.
double normalize()
Make a normalized vector (return norm value)
constexpr V3D cross_prod(const V3D &v) const noexcept
Cross product (this * argument)
constexpr double Y() const noexcept
Get y.
void rotate(const Matrix< double > &) noexcept
Rotate a point by a matrix.
double norm() const noexcept
constexpr double Z() const noexcept
Get z.
bool nullVector(const double tolerance=1e-3) const noexcept
Determine if the point is null.
MANTID_GEOMETRY_DLL Kernel::V3D inCylinder(const detail::ShapeInfo &shapeInfo, Kernel::PseudoRandomNumberGenerator &rng)
Return a random point in cylinder.
MANTID_GEOMETRY_DLL Kernel::V3D inCuboid(const detail::ShapeInfo &shapeInfo, Kernel::PseudoRandomNumberGenerator &rng)
Return a random point in a cuboid shape.
MANTID_GEOMETRY_DLL Kernel::V3D inSphere(const detail::ShapeInfo &shapeInfo, Kernel::PseudoRandomNumberGenerator &rng)
Return a random point in sphere.
MANTID_GEOMETRY_DLL Kernel::V3D inHollowCylinder(const detail::ShapeInfo &shapeInfo, Kernel::PseudoRandomNumberGenerator &rng)
Return a random point in a hollow cylinder.
MANTID_GEOMETRY_DLL boost::optional< Kernel::V3D > inGenericShape(const IObject &object, Kernel::PseudoRandomNumberGenerator &rng, size_t maxAttempts)
Return a random point in a generic shape.
boost::optional< Kernel::V3D > bounded(const detail::ShapeInfo &shapeInfo, Kernel::PseudoRandomNumberGenerator &rng, const BoundingBox &box, size_t maxAttempts)
Return a random point in a known shape restricted by a bounding box.
int convPartNum(const std::string &A, T &out)
Takes a character string and evaluates the first [typename T] object.
MANTID_KERNEL_DLL int StrLook(const std::string &, const boost::regex &)
Find is a pattern matches.
MANTID_KERNEL_DLL void writeMCNPX(const std::string &Line, std::ostream &OX)
Write file in standard MCNPX input form.
int convert(const std::string &A, T &out)
Convert a string into a number.
constexpr double Tolerance
Standard tolerance value.
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
std::string to_string(const wide_integer< Bits, Signed > &n)