Mantid
Loading...
Searching...
No Matches
InstrumentRayTracer.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7//-------------------------------------------------------------
8// Includes
9//-------------------------------------------------------------
15#include "MantidKernel/Matrix.h"
16#include "MantidKernel/Quat.h"
17#include "MantidKernel/V3D.h"
18#include <deque>
19#include <iterator>
20
21namespace Mantid::Geometry {
22
23using Kernel::V3D;
24
25//-------------------------------------------------------------
26// Public member functions
27//-------------------------------------------------------------
28
38 : m_componentInfo(componentInfo), m_detectorInfo(detectorInfo) {
40 std::string errorMsg = "Cannot create InstrumentRayTracer, instrument has "
41 "no defined source.\n";
42 throw std::invalid_argument(errorMsg);
43 }
44}
45
54void InstrumentRayTracer::trace(const V3D &dir) const {
55 // Define the track with the source position and the given direction.
57 // The intersection results are accumulated within the ray object
59}
60
70 // Define the track with the sample position and the given direction.
72 // The intersection results are accumulated within the ray object
74}
75
85
86//----------------------------------------------------------------------------------
93 Links const results = this->getResults();
94 auto const &compInfo = m_componentInfo;
95 auto const &detInfo = m_detectorInfo;
96
97 for (auto const &result : results) {
98 size_t const index = compInfo.indexOf(result.componentID);
99 if (compInfo.isDetector(index) && !detInfo.isMonitor(index))
100 return index;
101 }
103}
104
107
110
111//-------------------------------------------------------------
112// Private member functions
113//-------------------------------------------------------------
114
123 auto const &compInfo = m_componentInfo;
124 // Go through the instrument tree and see if we get any hits by
125 // (a) first testing the bounding box and if we're inside that then
126 // (b) test the lower components.
127 std::deque<size_t> nodeQueue;
128
129 // Start at the root of the tree
130 nodeQueue.emplace_back(compInfo.root());
131
132 while (!nodeQueue.empty()) {
133 size_t const node = nodeQueue.front();
134 nodeQueue.pop_front();
135 BoundingBox bbox;
136 auto it = m_boxCache.find(node);
137 if (it != m_boxCache.end()) {
138 bbox = it->second;
139 } else {
140 bbox = compInfo.boundingBox(node);
141 std::lock_guard<std::mutex> lock(m_mutex);
142 m_boxCache[node] = bbox;
143 }
144
145 // Quick test. If this suceeds moved on to test the children
146 if (!bbox.doesLineIntersect(testRay))
147 continue;
148 if (compInfo.isGridDetector(node)) {
149 testIntersectionWithGrid(node, testRay);
150 continue;
151 }
152 for (auto const child : compInfo.children(node)) {
153 if (!compInfo.children(child).empty())
154 nodeQueue.emplace_back(child);
155 else if (compInfo.hasValidShape(child))
156 testIntersectionWithShape(child, testRay);
157 }
158 }
159}
160
168 auto const &compInfo = m_componentInfo;
169 auto const &shape = compInfo.shape(index);
170 V3D const pos = compInfo.position(index);
171 Kernel::Quat const rot = compInfo.rotation(index);
172 Kernel::Quat unRotate = rot;
173 unRotate.inverse();
174 V3D const scale = compInfo.scaleFactor(index);
175
176 // Transform the track into the frame of the shape. As in
177 // ObjComponent::interceptSurface, scaling is not factored out here.
178 V3D trkStart = testRay.startPoint() - pos;
179 unRotate.rotate(trkStart);
180 V3D trkDirection = testRay.direction();
181 unRotate.rotate(trkDirection);
182
183 Track probeTrack(trkStart, trkDirection);
184 shape.interceptSurface(probeTrack);
185
186 for (auto const &link : probeTrack) {
187 V3D in = link.entryPoint;
188 rot.rotate(in);
189 in *= scale;
190 in += pos;
191 V3D out = link.exitPoint;
192 rot.rotate(out);
193 out *= scale;
194 out += pos;
195 // ComponentID is only used as a handle, so this is never written through
196 testRay.addLink(in, out, out.distance(testRay.startPoint()), shape,
197 const_cast<IComponent *>(compInfo.componentID(index)));
198 }
199}
200
208 auto const &compInfo = m_componentInfo;
209 auto const grid = compInfo.pixelGridComponent(index);
210
212 V3D const basePoint = compInfo.position(compInfo.detectorIndexAtXYZ(index, 0, 0, 0));
213
215 V3D const vertical = compInfo.position(compInfo.detectorIndexAtXYZ(index, 0, grid.nY - 1, 0)) - basePoint;
216
218 V3D const horizontal = compInfo.position(compInfo.detectorIndexAtXYZ(index, grid.nX - 1, 0, 0)) - basePoint;
219
220 // The beam direction
221 V3D const beam = testRay.direction();
222
223 // From: http://en.wikipedia.org/wiki/Line-plane_intersection (taken on May 4,
224 // 2011),
225 // We build a matrix to solve the linear equation:
226 Kernel::Matrix<double> mat(3, 3);
227 mat.setColumn(0, beam * -1.0);
228 mat.setColumn(1, horizontal);
229 mat.setColumn(2, vertical);
230 mat.Invert();
231
232 // Multiply by the inverted matrix to find t,u,v
233 V3D const tuv = mat * (testRay.startPoint() - basePoint);
234
235 // Intersection point
236 V3D const intersec = beam * tuv[0];
237
238 // t = coordinate along the line
239 // u,v = coordinates along horizontal, vertical
240 // (and correct for it being between 0, nX-1). The +0.5 is because the
241 // base point is at the CENTER of pixel 0,0.
242 auto const xIndex = int(double(grid.nX - 1) * tuv[1] + 0.5);
243 auto const yIndex = int(double(grid.nY - 1) * tuv[2] + 0.5);
244
245 // Out of range?
246 if (xIndex < 0 || yIndex < 0 || xIndex >= grid.nX || yIndex >= grid.nY)
247 return;
248
249 size_t const pixel = compInfo.detectorIndexAtXYZ(index, xIndex, yIndex, 0);
250 // ComponentID is only used as a handle, so this is never written through
251 testRay.addLink(intersec, intersec, 0.0, compInfo.shape(pixel),
252 const_cast<IComponent *>(compInfo.componentID(pixel)));
253}
254
256// * Perform a quick check as to whether the ray passes through the component
257// * @param component :: The test component
258// */
259// bool InstrumentRayTracer::quickIntersectCheck(std::shared_ptr<IComponent>
260// component, const Track & testRay) const
261// {
262//
263// }
264//
265// /**
266// * Perform a proper intersection test of the physical object and accumulate
267// the results if necessary
268// * @param testRay :: An input/output parameter that defines the track and
269// accumulates the
270// * intersection results
271// */
272// void slowIntersectCheck(std::shared_ptr<IComponent> component, Track &
273// testRay) const;
274} // namespace Mantid::Geometry
std::map< DeltaEMode::Type, std::string > index
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
Definition BoundingBox.h:33
bool doesLineIntersect(const Track &track) const
Does a specified track intersect the bounding box.
ComponentInfo : Provides a component centric view on to the instrument.
Beamline::PixelGridComponent pixelGridComponent(const size_t componentIndex) const
static constexpr size_t invalidIndex
Returned by indexOfOrInvalid() for a component ID that is not part of this instrument.
const Geometry::IObject & shape(const size_t componentIndex) const
Geometry::DetectorInfo is an intermediate step towards a DetectorInfo that is part of Instrument-2....
size_t indexOf(const detid_t id) const
Returns the index of the detector with the given detector ID.
base class for Geometric IComponent
Definition IComponent.h:53
const ComponentInfo & componentInfo() const
ComponentInfo/DetectorInfo for the traced instrument, against which the index returned by getDetector...
Links getResults() const
Get the results of the intersection tests that have been updated since the previous call to trace.
const DetectorInfo & detectorInfo() const
Track m_resultsTrack
Accumulate results in this Track object, aids performance.
InstrumentRayTracer(ComponentInfo const &componentInfo, DetectorInfo const &detectorInfo)
Constructor taking the ComponentInfo/DetectorInfo of the instrument to trace, which must outlive this...
void traceFromSample(const Kernel::V3D &dir) const
Trace a given track from the sample position in the given direction.
ComponentInfo const & m_componentInfo
ComponentInfo of the instrument being traced.
std::mutex m_mutex
Mutex to lock box cache.
boost::unordered_map< size_t, BoundingBox > m_boxCache
Map of component index -> bounding box.
void testIntersectionWithShape(size_t const index, Track &testRay) const
Intersect the track with the shape of a leaf component.
DetectorInfo const & m_detectorInfo
DetectorInfo of the instrument being traced.
void trace(const Kernel::V3D &dir) const
Trace a given track from the instrument source in the given direction and compile a list of results t...
size_t getDetectorResult() const
Get the index of the first non-monitor detector intersected since the previous call to trace,...
void testIntersectionWithGrid(size_t const index, Track &testRay) const
Intersect the track with the first layer of a Rectangular or Grid bank.
void fireRay(Track &testRay) const
Fire the given track at the instrument.
Defines a track as a start point and a direction.
Definition Track.h:165
const Kernel::V3D & startPoint() const
Returns the starting point.
Definition Track.h:191
int addLink(const Kernel::V3D &firstPoint, const Kernel::V3D &secondPoint, const double distanceAlongTrack, const IObject &obj, const ComponentID compID=nullptr)
Adds a link to the track.
Definition Track.cpp:152
void clearIntersectionResults()
Clear the current set of intersection results.
Definition Track.cpp:55
const Kernel::V3D & direction() const
Returns the direction as a unit vector.
Definition Track.h:193
LType::const_iterator cbegin() const
Returns an interator to the start of the set of links (const version)
Definition Track.h:206
LType::const_iterator cend() const
Returns an interator to one-past-the-end of the set of links (const version)
Definition Track.h:209
void reset(const Kernel::V3D &startPoint, const Kernel::V3D &direction)
Set a starting point and direction.
Definition Track.cpp:45
Numerical Matrix class.
Definition Matrix.h:41
T Invert()
LU inversion routine.
Definition Matrix.cpp:924
void setColumn(const size_t nCol, const std::vector< T > &newCol)
Definition Matrix.cpp:675
Class for quaternions.
Definition Quat.h:38
void inverse()
Inverse a quaternion (in the sense of rotation inversion)
Definition Quat.cpp:376
void rotate(V3D &) const
Rotate a vector.
Definition Quat.cpp:397
Class for 3D vectors.
Definition V3D.h:35
double distance(const V3D &v) const noexcept
Calculates the distance between two vectors.
Definition V3D.h:294
Track::LType Links
Typedef for object intersections.