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>
42#include <unordered_set>
51constexpr double VALID_INTERCEPT_POINT_SHIFT{2.5e-05};
65double triangleSolidAngle(
const V3D &a,
const V3D &b,
const V3D &c,
const V3D &observer) {
66 const V3D ao = a - observer;
67 const V3D bo = b - observer;
68 const V3D co = c - observer;
69 const double modao = ao.
norm();
70 const double modbo = bo.
norm();
71 const double modco = co.
norm();
76 const double denom = modao * modbo * modco + modco * aobo + modbo * aoco + modao * boco;
78 return 2.0 * atan2(scalTripProd, denom);
93 const double radius,
const double height) {
102 constexpr V3D initial_axis(0., 0., 1.0);
103 const Quat transform(initial_axis, axis_direction);
108 std::array<double, Mantid::Geometry::Cone::g_NSLICES> cos_table;
109 std::array<double, Mantid::Geometry::Cone::g_NSLICES> sin_table;
111 double solid_angle(0.0);
114 cos_table[vertex] = std::cos(angle_step * vertex);
115 sin_table[vertex] = std::sin(angle_step * vertex);
116 V3D pt2 =
V3D(radius * cos_table[vertex], radius * sin_table[vertex], 0.0);
120 cos_table[vertex] = std::cos(angle_step * vertex);
121 sin_table[vertex] = std::sin(angle_step * vertex);
125 V3D pt3 =
V3D(radius * cos_table[vertex], radius * sin_table[vertex], 0.0);
127 transform.rotate(pt2);
128 transform.rotate(pt3);
132 double sa = triangleSolidAngle(
centre, pt2, pt3, observer);
141 double z0(0.0), z1(z_step);
142 double r0(radius), r1(r0 - r_step);
149 V3D pt1 =
V3D(r0 * cos_table[vertex], r0 * sin_table[vertex], z0);
154 V3D pt3 =
V3D(r0 * cos_table[vertex], r0 * sin_table[vertex], z0);
157 V3D pt2 =
V3D(r1 * cos_table[vertex], r1 * sin_table[vertex], z1);
162 V3D pt4 =
V3D(r1 * cos_table[vertex], r1 * sin_table[vertex], z1);
164 transform.rotate(pt1);
165 transform.rotate(pt3);
166 transform.rotate(pt2);
167 transform.rotate(pt4);
173 double sa = triangleSolidAngle(pt1, pt4, pt3, observer);
177 sa = triangleSolidAngle(pt1, pt2, pt4, observer);
191 transform.
rotate(top_centre);
196 V3D pt2 =
V3D(r0 * cos_table[vertex], r0 * sin_table[vertex],
height);
202 V3D pt3 =
V3D(r0 * cos_table[vertex], r0 * sin_table[vertex],
height);
205 transform.rotate(pt2);
206 transform.rotate(pt3);
211 double sa = triangleSolidAngle(top_centre, pt3, pt2, observer);
228double cuboidSolidAngle(
const V3D &observer,
const std::vector<V3D> &vectors) {
233 std::vector<V3D> pts;
235 const V3D dx = vectors[1] - vectors[0];
236 const V3D dz = vectors[3] - vectors[0];
237 pts.emplace_back(vectors[2]);
238 pts.emplace_back(vectors[2] + dx);
239 pts.emplace_back(vectors[1]);
240 pts.emplace_back(vectors[0]);
241 pts.emplace_back(vectors[2] + dz);
242 pts.emplace_back(vectors[2] + dz + dx);
243 pts.emplace_back(vectors[1] + dz);
244 pts.emplace_back(vectors[0] + dz);
246 constexpr unsigned int ntriangles(12);
247 std::vector<std::vector<int>> triMap(ntriangles, std::vector<int>(3, 0));
285 for (
unsigned int i = 0; i < ntriangles; i++) {
286 const double sa = triangleSolidAngle(pts[triMap[i][0] - 1], pts[triMap[i][1] - 1], pts[triMap[i][2] - 1], observer);
303double cylinderSolidAngle(
const V3D &observer,
const V3D &
centre,
const V3D &axis,
const double radius,
304 const double height,
const int numberOfSlices) {
313 constexpr V3D initial_axis(0., 0., 1.0);
314 const Quat transform(initial_axis, axis);
317 const double angle_step = 2 * M_PI /
static_cast<double>(numberOfSlices);
320 double z0(0.0), z1(z_step);
321 double solid_angle(0.0);
328 for (
int sl = 0; sl < numberOfSlices; ++sl) {
329 double x = radius * std::cos(angle_step * sl);
330 double y = radius * std::sin(angle_step * sl);
333 int vertex = (sl + 1) % numberOfSlices;
334 x = radius * std::cos(angle_step * vertex);
335 y = radius * std::sin(angle_step * vertex);
339 transform.rotate(pt1);
340 transform.rotate(pt3);
341 transform.rotate(pt2);
342 transform.rotate(pt4);
349 double sa = triangleSolidAngle(pt1, pt4, pt3, observer);
353 sa = triangleSolidAngle(pt1, pt2, pt4, observer);
373double sphereSolidAngle(
const V3D &observer,
const std::vector<V3D> &vectors,
const double radius) {
374 const double distance = (observer - vectors[0]).norm();
375 if (distance > radius + Tolerance) {
376 const double sa = 2.0 * M_PI * (1.0 - cos(asin(radius / distance)));
378 }
else if (distance < radius - Tolerance)
400 : m_topRule(nullptr), m_boundingBox(), AABBxMax(0), AABByMax(0), AABBzMax(0), AABBxMin(0), AABByMin(0), AABBzMin(0),
401 boolBounded(false), m_objNum(0), m_handler(
std::make_shared<
GeometryHandler>(this)), bGeometryCaching(false),
481 static const boost::regex letters(
"[a-zA-Z]");
510 std::string::size_type pos = TopStr.find(
'#');
511 std::ostringstream cx;
512 while (pos != std::string::npos) {
514 cx << TopStr.substr(0, pos);
519 auto vc = MList.find(cN);
520 if (vc == MList.end())
524 cx << vc->second.cellStr(MList);
528 TopStr.erase(0, pos);
529 pos = TopStr.find(
'#');
555 std::deque<Rule *> rules;
557 while (!rules.empty()) {
558 Rule *T1 = rules.front();
562 auto *surface =
dynamic_cast<SurfPoint *
>(T1);
565 auto mapFound = surfMap.find(surface->getKeyN());
566 if (mapFound != surfMap.end()) {
567 surface->
setKey(mapFound->second);
577 rules.emplace_back(TA);
579 rules.emplace_back(TB);
598int CSGObject::procPair(std::string &lineStr, std::map<
int, std::unique_ptr<Rule>> &ruleMap,
int &compUnit)
const
605 for (Rstart = 0; Rstart < lineStr.size() && lineStr[Rstart] !=
'R'; Rstart++)
612 ruleMap.find(Ra) == ruleMap.end())
615 for (Rend = Rstart + 1; Rend < lineStr.size() && lineStr[Rend] !=
'R'; Rend++) {
616 if (lineStr[Rend] ==
':')
620 ruleMap.find(Rb) == ruleMap.end()) {
626 for (Rend++; Rend < lineStr.size() && lineStr[Rend] >=
'0' && lineStr[Rend] <=
'9'; Rend++)
631 (type) ? std::unique_ptr<Rule>(std::make_unique<Union>(std::move(ruleMap[Ra]), std::move(ruleMap[Rb])))
632 : std::unique_ptr<Rule>(std::make_unique<Intersection>(std::move(ruleMap[Ra]), std::move(ruleMap[Rb])));
633 ruleMap[Ra] = std::move(Join);
634 ruleMap.erase(ruleMap.find(Rb));
638 for (strPos = Rstart - 1; strPos >= 0 && lineStr[strPos] ==
' '; strPos--)
640 Rstart = (strPos < 0) ? 0 : strPos;
641 for (strPos = Rend; strPos < static_cast<int>(lineStr.size()) && lineStr[strPos] ==
' '; strPos++)
645 std::stringstream newRuleStr;
646 newRuleStr <<
" R" << Ra <<
" ";
647 lineStr.replace(Rstart, Rend, newRuleStr.str());
659 return std::make_unique<CompGrp>();
662 const Rule *RItemptr = ruleItem.get();
663 auto CG = std::make_unique<CompGrp>(Pptr, std::move(ruleItem));
665 const int Ln = Pptr->
findLeaf(RItemptr);
666 Pptr->
setLeaf(std::move(CG), Ln);
668 return std::make_unique<CompGrp>();
692 std::vector<Kernel::V3D> Snorms;
696 if ((*vc)->onSurface(point)) {
697 Snorms.emplace_back((*vc)->surfaceNormal(point));
705 for (
auto xs = Snorms.begin(); xs != Snorms.end(); ++xs)
706 for (
auto ys = std::next(xs); ys != Snorms.end(); ++ys) {
707 NormPair = (*ys) + (*xs);
712 }
catch (std::runtime_error &) {
768 std::stack<const Rule *> TreeLine;
770 while (!TreeLine.empty()) {
771 const Rule *tmpA = TreeLine.top();
781 const auto *SurX =
dynamic_cast<const SurfPoint *
>(tmpA);
788 std::unordered_set<const Surface *> uniqueSurfacePtrs;
791 if (uniqueSurfacePtrs.find(sPtr) != std::end(uniqueSurfacePtrs)) {
794 uniqueSurfacePtrs.insert(sPtr);
798 m_surList.erase(newEnd, m_surList.end());
802 std::vector<const Surface *>::const_iterator vc;
803 for (vc = m_surList.begin(); vc != m_surList.end(); ++vc) {
804 logger.debug() <<
"Point == " << *vc <<
'\n';
805 logger.debug() << (*vc)->getName() <<
'\n';
816 std::vector<int> out;
817 transform(
m_surList.begin(),
m_surList.end(), std::insert_iterator<std::vector<int>>(out, out.begin()),
848 const int out =
m_topRule->substituteSurf(surfNum, newSurfNum, surfPtr);
858 std::deque<Rule *> rst;
859 std::vector<int> Cells;
864 while (!rst.empty()) {
865 const Rule *T1 = rst.front();
869 const auto *surface =
dynamic_cast<const SurfPoint *
>(T1);
871 Cells.emplace_back(surface->getKeyN());
876 rst.emplace_back(TA);
878 rst.emplace_back(TB);
883 logger.debug() <<
"Name == " <<
m_objNum <<
'\n';
884 logger.debug() <<
"Rules == " << Rcount <<
'\n';
885 std::vector<int>::const_iterator mc;
886 logger.debug() <<
"Surface included == ";
887 for (mc = Cells.begin(); mc < Cells.end(); ++mc) {
888 logger.debug() << (*mc) <<
" ";
890 logger.debug() <<
'\n';
905 logger.debug() <<
"Name == " <<
m_objNum <<
'\n';
906 logger.debug() <<
m_topRule->display() <<
'\n';
915 std::ostringstream objStr;
927 std::ostringstream objStr;
941 std::ostringstream objStr;
942 objStr.precision(10);
954 std::map<int, std::unique_ptr<Rule>> RuleList;
958 std::unique_ptr<SurfPoint> TmpR;
959 std::unique_ptr<CompObj> TmpO;
961 std::string Ln = lineStr;
963 std::ostringstream cx;
964 const std::string::size_type length = Ln.length();
965 for (
size_t i = 0; i < length; i++) {
966 if (isdigit(Ln[i]) || Ln[i] ==
'-') {
970 throw std::invalid_argument(
"Invalid surface string in Object::ProcString : " + lineStr);
972 if (i != 0 && Ln[i - 1] ==
'#') {
973 TmpO = std::make_unique<CompObj>();
975 RuleList[Ridx] = std::move(TmpO);
978 TmpR = std::make_unique<SurfPoint>();
980 RuleList[Ridx] = std::move(TmpR);
982 cx <<
" R" << Ridx <<
" ";
992 int brack_exists = 1;
993 while (brack_exists) {
994 std::string::size_type rbrack = Ln.find(
')');
995 std::string::size_type lbrack = Ln.rfind(
'(', rbrack);
996 if (rbrack != std::string::npos && lbrack != std::string::npos) {
997 std::string Lx = Ln.substr(lbrack + 1, rbrack - lbrack - 1);
1000 while (
procPair(Lx, RuleList, compUnit))
1002 Ln.replace(lbrack, 1 + rbrack - lbrack, Lx);
1005 for (hCnt =
static_cast<int>(lbrack) - 1; hCnt >= 0 && isspace(Ln[hCnt]); hCnt--)
1007 if (hCnt >= 0 && Ln[hCnt] ==
'#') {
1008 RuleList[compUnit] =
procComp(std::move(RuleList[compUnit]));
1009 Ln.erase(hCnt, lbrack - hCnt);
1016 while (
procPair(Ln, RuleList, nullInt)) {
1019 if (RuleList.size() == 1) {
1020 m_topRule = std::move((RuleList.begin())->second);
1022 throw std::logic_error(
"Object::procString() - Unexpected number of "
1023 "surface rules found. Expected=1, found=" +
1035 int originalCount = track.
count();
1042 surface->acceptVisitor(LI);
1055 const size_t nPoints(IPoints.size());
1058 for (
size_t i = 0; i < nPoints; i++) {
1064 const auto ¤tPt(IPoints[i]);
1065 const auto &prePt((i == 0 || dPoints[i - 1] <= 0) ? track.
startPoint() : IPoints[i - 1]);
1066 const auto &nextPt(i + 1 < nPoints ? IPoints[i + 1] : currentPt + currentPt - prePt);
1072 track.
addPoint(trackType, currentPt, *
this);
1078 return (track.
count() - originalCount);
1090 surface->acceptVisitor(LI);
1094 if (!distances.empty()) {
1095 return std::abs(*std::min_element(std::begin(distances), std::end(distances)));
1097 std::ostringstream os;
1098 os <<
"Unable to find intersection with object with track starting at " << track.
startPoint() <<
" in direction "
1100 throw std::runtime_error(os.str());
1116 const Kernel::V3D shift(uVec * VALID_INTERCEPT_POINT_SHIFT);
1117 const int flagA =
isValid(point - shift);
1118 const int flagB =
isValid(point + shift);
1119 if (!(flagA ^ flagB))
1136 const auto upstreamPt = (prePt + curPt) * 0.5;
1137 const auto upstreamPtInsideShape =
isValid(upstreamPt);
1139 const auto downstreamPt = (curPt + nxtPt) * 0.5;
1140 const auto downstreamPtInsideShape =
isValid(downstreamPt);
1158 if (!(upstreamPtInsideShape ^ downstreamPtInsideShape))
1207 const int resNoBB = 200, resPhiMin = 10;
1208 int res = resNoBB, itheta, jphi, resPhi;
1209 double theta, phi, sum, dphi, dtheta;
1216 double thetaMax = M_PI;
1217 bool useBB =
false, usePt =
false;
1223 useBB = usePt =
true;
1226 const int resBB = 100;
1236 ptInObject -= observer;
1237 double theta0 = -180.0 / M_PI * acos(ptInObject.
Z() / ptInObject.
norm());
1242 zToPt(theta0, axis);
1244 dtheta = thetaMax / res;
1245 int count = 0, countPhi;
1247 for (itheta = 1; itheta <= res; itheta++) {
1249 theta = thetaMax * (itheta - 0.5) / res;
1250 resPhi =
static_cast<int>(res * sin(theta));
1251 if (resPhi < resPhiMin)
1253 dphi = 2 * M_PI / resPhi;
1255 for (jphi = 1; jphi <= resPhi; jphi++) {
1257 phi = 2.0 * M_PI * (jphi - 0.5) / resPhi;
1258 Kernel::V3D dir(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
1262 Track tr(observer, dir);
1264 sum += dtheta * dphi * sin(theta);
1271 if (!useBB && countPhi == 0)
1275 if (!useBB &&
count < resPhiMin + 1) {
1278 thetaMax = thetaMax * (itheta - 0.5) / res;
1279 dtheta = thetaMax / res;
1281 for (itheta = 1; itheta <= res; itheta++) {
1282 theta = thetaMax * (itheta - 0.5) / res;
1283 resPhi =
static_cast<int>(res * sin(theta));
1284 if (resPhi < resPhiMin)
1286 dphi = 2 * M_PI / resPhi;
1288 for (jphi = 1; jphi <= resPhi; jphi++) {
1289 phi = 2.0 * M_PI * (jphi - 0.5) / resPhi;
1290 Kernel::V3D dir(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
1293 Track tr(observer, dir);
1295 sum += dtheta * dphi * sin(theta);
1320 const auto &observer = params.
observer();
1325 return (2.0 * M_PI);
1327 return (4.0 * M_PI);
1332 double height(0.0), radius(0.0), innerRadius(0.0);
1334 std::vector<Mantid::Kernel::V3D> geometry_vectors;
1336 geometry_vectors.reserve(4);
1343 return cuboidSolidAngle(observer, geometry_vectors);
1346 return sphereSolidAngle(observer, geometry_vectors, radius);
1349 return cylinderSolidAngle(observer, geometry_vectors[0], geometry_vectors[1], radius,
height,
1353 return coneSolidAngle(observer, geometry_vectors[0], geometry_vectors[1], radius,
height);
1362 double sangle(0.0), sneg(0.0);
1363 for (
size_t i = 0; i < nTri; i++) {
1364 int p1 = faces[i * 3], p2 = faces[i * 3 + 1], p3 = faces[i * 3 + 2];
1365 V3D vp1 =
V3D(vertices[3 * p1], vertices[3 * p1 + 1], vertices[3 * p1 + 2]);
1366 V3D vp2 =
V3D(vertices[3 * p2], vertices[3 * p2 + 1], vertices[3 * p2 + 2]);
1367 V3D vp3 =
V3D(vertices[3 * p3], vertices[3 * p3 + 1], vertices[3 * p3 + 2]);
1368 double sa = triangleSolidAngle(vp1, vp2, vp3, observer);
1387 return 0.5 * (sangle - sneg);
1407 const auto &observer = params.
observer();
1409 double sx = scaleFactor[0], sy = scaleFactor[1], sz = scaleFactor[2];
1410 const V3D sObserver = observer;
1414 return (2.0 * M_PI);
1416 return (4.0 * M_PI);
1427 double height = 0.0, radius(0.0), innerRadius;
1429 std::vector<Kernel::V3D> vectors;
1433 std::transform(vectors.begin(), vectors.end(), vectors.begin(),
1434 [scaleFactor](
const V3D &v) { return v * scaleFactor; });
1435 return cuboidSolidAngle(observer, vectors);
1438 return sphereSolidAngle(observer, vectors, radius);
1451 double sangle(0.0), sneg(0.0);
1452 for (
size_t i = 0; i < nTri; i++) {
1453 int p1 = faces[i * 3], p2 = faces[i * 3 + 1], p3 = faces[i * 3 + 2];
1456 V3D vp1 =
V3D(sx * vertices[3 * p1], sy * vertices[3 * p1 + 1], sz * vertices[3 * p1 + 2]);
1457 V3D vp2 =
V3D(sx * vertices[3 * p2], sy * vertices[3 * p2 + 1], sz * vertices[3 * p2 + 2]);
1458 V3D vp3 =
V3D(sx * vertices[3 * p3], sy * vertices[3 * p3 + 1], sz * vertices[3 * p3 + 2]);
1459 double sa = triangleSolidAngle(vp1, vp2, vp3, observer);
1465 return (0.5 * (sangle - sneg));
1478 std::vector<Kernel::V3D> vectors;
1485 double volumeTri = 0.0;
1509 return volumeTri / 6;
1512 return 4.0 / 3.0 * M_PI * radius * radius * radius;
1514 return M_PI * radius * radius *
height;
1516 return M_PI *
height * (radius * radius - innerRadius * innerRadius);
1530 using namespace boost::accumulators;
1531 const int singleShotIterations = 10000;
1532 accumulator_set<double, features<tag::mean, tag::error_of<tag::mean>>> accumulate;
1534 std::ranlux48 rnEngine;
1536 for (
int i = 0; i < 10; ++i) {
1537 const auto seed = rnEngine();
1539 accumulate(volumeMc);
1541 const double relativeErrorTolerance = 1e-3;
1543 double currentError;
1545 const auto seed = rnEngine();
1547 accumulate(volumeMc);
1548 currentMean = mean(accumulate);
1549 currentError = error_of<tag::mean>(accumulate);
1550 if (std::isnan(currentError)) {
1553 }
while (currentError / currentMean > relativeErrorTolerance);
1565 if (boundingBox.isNull()) {
1566 throw std::runtime_error(
"Cannot calculate volume: invalid bounding box.");
1569 const double boundingDx = boundingBox.xMax() - boundingBox.xMin();
1570 const double boundingDy = boundingBox.yMax() - boundingBox.yMin();
1571 const double boundingDz = boundingBox.zMax() - boundingBox.zMin();
1575 size_t blocksize = shotSize / threadCount;
1577 if (currentThreadNum == threadCount - 1) {
1580 blocksize = shotSize - (threadCount - 1) * blocksize;
1582 std::mt19937 rnEngine(
static_cast<std::mt19937::result_type
>(seed));
1588 rnEngine.discard(currentThreadNum * 3 * blocksize);
1589 std::uniform_real_distribution<double> rnDistribution(0.0, 1.0);
1591 for (
int i = 0; i < static_cast<int>(blocksize); ++i) {
1592 double rnd = rnDistribution(rnEngine);
1593 const double x = boundingBox.xMin() + rnd * boundingDx;
1594 rnd = rnDistribution(rnEngine);
1595 const double y = boundingBox.yMin() + rnd * boundingDy;
1596 rnd = rnDistribution(rnEngine);
1597 const double z = boundingBox.zMin() + rnd * boundingDz;
1606 const double ratio =
static_cast<double>(totalHits) /
static_cast<double>(shotSize);
1607 const double boundingVolume = boundingDx * boundingDy * boundingDz;
1608 return ratio * boundingVolume;
1668 const double huge(1e10);
1669 const double big(1e4);
1670 double minX(-huge), minY(-huge), minZ(-huge);
1671 double maxX(huge), maxY(huge), maxZ(huge);
1674 m_topRule->getBoundingBox(maxX, maxY, maxZ, minX, minY, minZ);
1678 if (minX > -big && maxX < big && minY > -big && maxY < big && minZ > -big && maxZ < big && minX <= maxX &&
1679 minY <= maxY && minZ <= maxZ) {
1697 if (vertCount > 0) {
1700 constexpr double huge = 1e10;
1701 double minX, maxX, minY, maxY, minZ, maxZ;
1702 minX = minY = minZ = huge;
1703 maxX = maxY = maxZ = -huge;
1706 for (
size_t i = 0; i < vertCount; ++i) {
1707 auto vx = vertArray[3 * i + 0];
1708 auto vy = vertArray[3 * i + 1];
1709 auto vz = vertArray[3 * i + 2];
1711 minX = std::min(minX, vx);
1712 maxX = std::max(maxX, vx);
1713 minY = std::min(minY, vy);
1714 maxY = std::max(maxY, vy);
1715 minZ = std::min(minZ, vz);
1716 maxZ = std::max(maxZ, vz);
1736 double minX, maxX, minY, maxY, minZ, maxZ;
1740 std::vector<Kernel::V3D> vectors;
1751 const auto &lfb = vectors[0];
1752 const auto &lft = vectors[1];
1753 const auto &lbb = vectors[2];
1754 const auto &rfb = vectors[3];
1757 auto lbt = lft + (lbb - lfb);
1758 auto rft = rfb + (lft - lfb);
1759 auto rbb = lbb + (rfb - lfb);
1760 auto rbt = rbb + (rft - rfb);
1762 vectors.emplace_back(lbt);
1763 vectors.emplace_back(rft);
1764 vectors.emplace_back(rbb);
1765 vectors.emplace_back(rbt);
1768 constexpr double huge = 1e10;
1769 minX = minY = minZ = huge;
1770 maxX = maxY = maxZ = -huge;
1773 for (
const auto &vector : vectors) {
1774 minX = std::min(minX, vector.X());
1775 maxX = std::max(maxX, vector.X());
1776 minY = std::min(minY, vector.Y());
1777 maxY = std::max(maxY, vector.Y());
1778 minZ = std::min(minZ, vector.Z());
1779 maxZ = std::max(maxZ, vector.Z());
1784 minX = minY = minZ = std::numeric_limits<
decltype(minZ)>::max();
1785 maxX = maxY = maxZ = -std::numeric_limits<
decltype(maxZ)>::max();
1788 for (
const auto &vector : vectors) {
1789 minX = std::min(minX, vector.X());
1790 maxX = std::max(maxX, vector.X());
1791 minY = std::min(minY, vector.Y());
1792 maxY = std::max(maxY, vector.Y());
1793 minZ = std::min(minZ, vector.Z());
1794 maxZ = std::max(maxZ, vector.Z());
1799 const auto &base = vectors[0];
1800 const auto &axis = vectors[1];
1806 volatile auto rx = radius * sqrt(pow(axis.
Y(), 2) + pow(axis.
Z(), 2));
1807 volatile auto ry = radius * sqrt(pow(axis.
X(), 2) + pow(axis.
Z(), 2));
1808 volatile auto rz = radius * sqrt(pow(axis.
X(), 2) + pow(axis.
Y(), 2));
1812 minX = std::min(base.X(),
top.X()) - rx;
1813 maxX = std::max(base.X(),
top.X()) + rx;
1814 minY = std::min(base.Y(),
top.Y()) - ry;
1815 maxY = std::max(base.Y(),
top.Y()) + ry;
1816 minZ = std::min(base.Z(),
top.Z()) - rz;
1817 maxZ = std::max(base.Z(),
top.Z()) + rz;
1821 const auto &tip = vectors[0];
1822 const auto &axis = vectors[1];
1823 auto base = tip + (axis *
height);
1828 auto rx = radius * sqrt(pow(axis.
Y(), 2) + pow(axis.
Z(), 2));
1829 auto ry = radius * sqrt(pow(axis.
X(), 2) + pow(axis.
Z(), 2));
1830 auto rz = radius * sqrt(pow(axis.
X(), 2) + pow(axis.
Y(), 2));
1833 minX = std::min(tip.X(), base.X() - rx);
1834 maxX = std::max(tip.X(), base.X() + rx);
1835 minY = std::min(tip.Y(), base.Y() - ry);
1836 maxY = std::max(tip.Y(), base.Y() + ry);
1837 minZ = std::min(tip.Z(), base.Z() - rz);
1838 maxZ = std::max(tip.Z(), base.Z() + rz);
1862 double &zmin)
const {
1864 xmax = ymax = zmax = xmin = ymin = zmin = 0.0;
1875 if (
AABBxMax >= xmax || AABBxMin <= xmin || AABByMax >= ymax || AABByMin <= ymin || AABBzMax >= zmax ||
1904 const double &yMin,
const double &zMin) {
1963 const size_t maxAttempts)
const {
1964 std::optional<V3D> point{std::nullopt};
1972 const size_t bruteForceAttempts{std::min(
static_cast<size_t>(5), maxAttempts)};
2010 const size_t maxAttempts)
const {
2011 std::optional<V3D> point{std::nullopt};
2018 const size_t bruteForceAttempts{std::min(
static_cast<size_t>(5), maxAttempts)};
2022 std::vector<Kernel::V3D> shapeVectors;
2027 switch (shapeGeometry) {
2029 point = RandomPoint::bounded<RandomPoint::inCuboid>(
m_handler->shapeInfo(), rng, activeRegion,
2030 maxAttempts - bruteForceAttempts);
2033 point = RandomPoint::bounded<RandomPoint::inCylinder>(
m_handler->shapeInfo(), rng, activeRegion,
2034 maxAttempts - bruteForceAttempts);
2037 point = RandomPoint::bounded<RandomPoint::inHollowCylinder>(
m_handler->shapeInfo(), rng, activeRegion,
2038 maxAttempts - bruteForceAttempts);
2041 point = RandomPoint::bounded<RandomPoint::inSphere>(
m_handler->shapeInfo(), rng, activeRegion,
2042 maxAttempts - bruteForceAttempts);
2064 for (
const auto &dir :
2065 {
V3D(1., 0., 0.),
V3D(-1., 0., 0.),
V3D(0., 1., 0.),
V3D(0., -1., 0.),
V3D(0., 0., 1.),
V3D(0., 0., -1.)}) {
2068 point = tr.
cbegin()->entryPoint;
2169 static const std::vector<double> empty;
2172 return m_handler->getTriangleVertices();
2179 static const std::vector<uint32_t> empty;
2197 throw std::logic_error(
"CSGObject has no ShapeInfo to return");
2205 double &innerRadius,
double &radius,
double &
height)
const {
#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 solidAngle(const SolidAngleParams ¶ms) const override
Find solid angle of object wrt the observer.
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
get faces
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 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
Kernel::Matrix< double > m_appliedRotation
Rotation already applied to the shape definition, from a "goniometer" tag in the XML.
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.
double triangulatedSolidAngle(const SolidAngleParams ¶ms) const
Find solid angle of object from point "observer" using the OC triangulation of the object,...
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,...
void procString(const std::string &lineStr)
Processes the cell string.
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.
detail::ShapeInfo::GeometryShape shape() const override
std::optional< Kernel::V3D > generatePointInObject(Kernel::PseudoRandomNumberGenerator &rng, const size_t) const override
Select a random point within the object.
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.
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.
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.
int cylinderSlices() const
const Kernel::V3D & observer() const
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.
std::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.
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 std::optional< Kernel::V3D > inGenericShape(const IObject &object, Kernel::PseudoRandomNumberGenerator &rng, size_t maxAttempts)
Return a random point in a generic shape.
MANTID_GEOMETRY_DLL Kernel::V3D inHollowCylinder(const detail::ShapeInfo &shapeInfo, Kernel::PseudoRandomNumberGenerator &rng)
Return a random point in a hollow cylinder.
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)