Mantid
Loading...
Searching...
No Matches
ComponentInfo.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 +
8#include "MantidBeamline/ComponentInfo.h"
9#include "MantidBeamline/ComponentType.h"
15
16#include <Eigen/Geometry>
17#include <exception>
18#include <iterator>
19#include <string>
20
21namespace Mantid::Geometry {
22
23namespace {
27const Eigen::Vector3d undoRotation(const Eigen::Vector3d &point, const Beamline::ComponentInfo &compInfo,
28 const size_t componentIndex) {
29 auto unRotateTransform = Eigen::Affine3d(compInfo.rotation(componentIndex).inverse());
30 return unRotateTransform * point;
31}
39const Kernel::V3D toShapeFrame(const Kernel::V3D &point, const Beamline::ComponentInfo &compInfo,
40 const size_t componentIndex) {
41 return Kernel::toV3D(
42 undoRotation(Kernel::toVector3d(point) - compInfo.position(componentIndex), compInfo, componentIndex));
43}
44
45} // namespace
46
55 std::unique_ptr<Beamline::ComponentInfo> componentInfo,
56 std::shared_ptr<const std::vector<Mantid::Geometry::IComponent *>> componentIds,
57 std::shared_ptr<const std::unordered_map<Geometry::IComponent *, size_t>> componentIdToIndexMap,
58 std::shared_ptr<std::vector<std::shared_ptr<const Geometry::IObject>>> shapes)
59 : m_componentInfo(std::move(componentInfo)), m_componentIds(std::move(componentIds)),
60 m_compIDToIndex(std::move(componentIdToIndexMap)), m_shapes(std::move(shapes)) {
61
62 if (m_componentIds->size() != m_compIDToIndex->size()) {
63 throw std::invalid_argument("Inconsistent ID and Mapping input containers "
64 "for Geometry::ComponentInfo");
65 }
66 if (m_componentIds->size() != m_componentInfo->size()) {
67 throw std::invalid_argument("Inconsistent ID and base "
68 "Beamline::ComponentInfo sizes for "
69 "Geometry::ComponentInfo");
70 }
71}
72
77std::unique_ptr<Geometry::ComponentInfo> ComponentInfo::cloneWithoutDetectorInfo() const {
78
79 return std::unique_ptr<Geometry::ComponentInfo>(new Geometry::ComponentInfo(*this));
80}
81
87 : m_componentInfo(other.m_componentInfo->cloneWithoutDetectorInfo()), m_componentIds(other.m_componentIds),
88 m_compIDToIndex(other.m_compIDToIndex), m_shapes(other.m_shapes) {}
89
90// Defined as default in source for forward declaration with std::unique_ptr.
92
93std::vector<size_t> ComponentInfo::detectorsInSubtree(size_t componentIndex) const {
94 return m_componentInfo->detectorsInSubtree(componentIndex);
95}
96
97std::vector<size_t> ComponentInfo::componentsInSubtree(size_t componentIndex) const {
98 return m_componentInfo->componentsInSubtree(componentIndex);
99}
100
101const std::vector<size_t> &ComponentInfo::children(size_t componentIndex) const {
102 return m_componentInfo->children(componentIndex);
103}
104
105size_t ComponentInfo::size() const { return m_componentInfo->size(); }
106
108 auto type = componentType(componentIndex);
109 auto parentType = componentType(parent(componentIndex));
110 if (!(type == Beamline::ComponentType::Structured || type == Beamline::ComponentType::Rectangular ||
111 parentType == Beamline::ComponentType::Grid))
112 throw std::runtime_error("ComponentType is not Structured or Rectangular "
113 "in ComponentInfo::quadrilateralComponent.");
114
116 const auto &innerRangeComp = m_componentInfo->children(componentIndex);
117 corners.nX = innerRangeComp.size();
118 const auto &firstCol = m_componentInfo->children(innerRangeComp[0]);
119 const auto &lastCol = m_componentInfo->children(innerRangeComp[corners.nX - 1]);
120 corners.nY = firstCol.size();
121 corners.bottomLeft = firstCol.front();
122 corners.topRight = lastCol.back();
123 corners.topLeft = firstCol.back();
124 corners.bottomRight = lastCol.front();
125
126 return corners;
127}
128
130
131size_t ComponentInfo::indexOfAny(const std::string &name) const { return m_componentInfo->indexOfAny(name); }
132
133bool ComponentInfo::uniqueName(const std::string &name) const { return m_componentInfo->uniqueName(name); }
134
135bool ComponentInfo::isDetector(const size_t componentIndex) const {
136 return m_componentInfo->isDetector(componentIndex);
137}
138
139bool ComponentInfo::hasValidShape(const size_t componentIndex) const {
140 const auto *shape = (*m_shapes)[componentIndex].get();
141 return shape != nullptr && shape->hasValidShape();
142}
143
144Kernel::V3D ComponentInfo::position(const size_t componentIndex) const {
145 return Kernel::toV3D(m_componentInfo->position(componentIndex));
146}
147
148Kernel::V3D ComponentInfo::position(const std::pair<size_t, size_t> &index) const {
149 return Kernel::toV3D(m_componentInfo->position(index));
150}
151
152Kernel::Quat ComponentInfo::rotation(const size_t componentIndex) const {
153 return Kernel::toQuat(m_componentInfo->rotation(componentIndex));
154}
155
156Kernel::Quat ComponentInfo::rotation(const std::pair<size_t, size_t> &index) const {
157 return Kernel::toQuat(m_componentInfo->rotation(index));
158}
159
160Kernel::V3D ComponentInfo::relativePosition(const size_t componentIndex) const {
161 return Kernel::toV3D(m_componentInfo->relativePosition(componentIndex));
162}
163
164Kernel::Quat ComponentInfo::relativeRotation(const size_t componentIndex) const {
165 return Kernel::toQuat(m_componentInfo->relativeRotation(componentIndex));
166}
167
168void ComponentInfo::setPosition(const std::pair<size_t, size_t> &index, const Kernel::V3D &newPosition) {
169 m_componentInfo->setPosition(index, Kernel::toVector3d(newPosition));
170}
171
172void ComponentInfo::setRotation(const std::pair<size_t, size_t> &index, const Kernel::Quat &newRotation) {
173 m_componentInfo->setRotation(index, Kernel::toQuaterniond(newRotation));
174}
175
176size_t ComponentInfo::parent(const size_t componentIndex) const { return m_componentInfo->parent(componentIndex); }
177
178bool ComponentInfo::hasParent(const size_t componentIndex) const { return m_componentInfo->hasParent(componentIndex); }
179
180bool ComponentInfo::hasDetectorInfo() const { return m_componentInfo->hasDetectorInfo(); }
181
183
185
186bool ComponentInfo::hasSource() const { return m_componentInfo->hasSource(); }
187
188/*
189 * @brief Check the sources of two componentInfo objects coincide
190 *
191 * @details check both objects either lack or have a source. If the latter,
192 * check their positions differ by less than 1 nm = 1e-9 m.
193 *
194 * @returns true if sources are equivalent
195 */
197 return m_componentInfo->hasEquivalentSource(*(other.m_componentInfo));
198}
199
200bool ComponentInfo::hasSample() const { return m_componentInfo->hasSample(); }
201
202/*
203 * @brief Check the samples of two componentInfo objects coincide
204 *
205 * @details check both objects either lack or have a sample. If the latter,
206 * check their positions differ by less than 1 nm = 1e-9 m.
207 *
208 * @returns true if sources are equivalent
209 */
211 return m_componentInfo->hasEquivalentSample(*(other.m_componentInfo));
212}
213
214bool ComponentInfo::hasDetectors(const size_t componentIndex) const {
215 if (isDetector(componentIndex))
216 return false;
217 const auto range = m_componentInfo->detectorRangeInSubtree(componentIndex);
218 return range.begin() < range.end();
219}
220
221size_t ComponentInfo::source() const { return m_componentInfo->source(); }
222
223size_t ComponentInfo::sample() const { return m_componentInfo->sample(); }
224
225double ComponentInfo::l1() const { return m_componentInfo->l1(); }
226
227size_t ComponentInfo::root() const { return m_componentInfo->root(); }
228
229void ComponentInfo::setPosition(const size_t componentIndex, const Kernel::V3D &newPosition) {
230 m_componentInfo->setPosition(componentIndex, Kernel::toVector3d(newPosition));
231}
232
233void ComponentInfo::setRotation(const size_t componentIndex, const Kernel::Quat &newRotation) {
234 m_componentInfo->setRotation(componentIndex, Kernel::toQuaterniond(newRotation));
235}
236
237const IObject &ComponentInfo::shape(const size_t componentIndex) const { return *(*m_shapes)[componentIndex]; }
238
239Kernel::V3D ComponentInfo::scaleFactor(const size_t componentIndex) const {
240 return Kernel::toV3D(m_componentInfo->scaleFactor(componentIndex));
241}
242
243const std::string &ComponentInfo::name(const size_t componentIndex) const {
244 return m_componentInfo->name(componentIndex);
245}
246
247void ComponentInfo::setScaleFactor(const size_t componentIndex, const Kernel::V3D &scaleFactor) {
248 m_componentInfo->setScaleFactor(componentIndex, Kernel::toVector3d(scaleFactor));
249}
250
251double ComponentInfo::solidAngle(const size_t componentIndex, const Kernel::V3D &observer) const {
252 if (!hasValidShape(componentIndex))
253 throw Kernel::Exception::NullPointerException("ComponentInfo::solidAngle", "shape");
254 // This is the observer position in the shape's coordinate system.
255 const Kernel::V3D relativeObserver = toShapeFrame(observer, *m_componentInfo, componentIndex);
256 const Kernel::V3D scaleFactor = this->scaleFactor(componentIndex);
257 if ((scaleFactor - Kernel::V3D(1.0, 1.0, 1.0)).norm() < 1e-12)
258 return shape(componentIndex).solidAngle(relativeObserver);
259 else {
260 // This function will scale the object shape when calculating the solid
261 // angle.
262 return shape(componentIndex).solidAngle(relativeObserver, scaleFactor);
263 }
264}
265
284 Geometry::BoundingBox &mutableBB,
285 const bool excludeMonitors) const {
286
287 auto panel = quadrilateralComponent(index);
288 mutableBB.grow(componentBoundingBox(panel.bottomLeft, reference, excludeMonitors));
289 mutableBB.grow(componentBoundingBox(panel.topRight, reference, excludeMonitors));
290 mutableBB.grow(componentBoundingBox(panel.topLeft, reference, excludeMonitors));
291 mutableBB.grow(componentBoundingBox(panel.bottomRight, reference, excludeMonitors));
292}
293
305 const bool excludeMonitors) const {
306 mutableBB.grow(componentBoundingBox(index, reference, excludeMonitors));
307}
308
319 const bool excludeMonitors) const {
320 // Check that we have a valid shape here
321 if (componentType(index) == Beamline::ComponentType::Infinite) {
322 return BoundingBox(); // Return null bounding box
323 }
324 if (excludeMonitors) {
325 // skip monitors
326 if (isDetector(index) && m_componentInfo->isMonitor(index)) {
327 return BoundingBox();
328 }
329 // skip other components such as choppers, etc
330 if (componentType(index) == Beamline::ComponentType::Generic) {
331 return BoundingBox();
332 }
333 }
334 if (!hasValidShape(index)) {
335 return BoundingBox(this->position(index).X(), this->position(index).Y(), this->position(index).Z(),
336 this->position(index).X(), this->position(index).Y(), this->position(index).Z());
337 } else {
338 const auto &s = this->shape(index);
339 BoundingBox absoluteBB = s.getBoundingBox();
340
341 // modify in place for speed
342 const Eigen::Vector3d scaleFactor = m_componentInfo->scaleFactor(index);
343 // Scale
344 absoluteBB.xMin() *= scaleFactor[0];
345 absoluteBB.xMax() *= scaleFactor[0];
346 absoluteBB.yMin() *= scaleFactor[1];
347 absoluteBB.yMax() *= scaleFactor[1];
348 absoluteBB.zMin() *= scaleFactor[2];
349 absoluteBB.zMax() *= scaleFactor[2];
350 // Rotate
351 (this->rotation(index))
352 .rotateBB(absoluteBB.xMin(), absoluteBB.yMin(), absoluteBB.zMin(), absoluteBB.xMax(), absoluteBB.yMax(),
353 absoluteBB.zMax());
354
355 // Shift
356 const Eigen::Vector3d localPos = m_componentInfo->position(index);
357 absoluteBB.xMin() += localPos[0];
358 absoluteBB.xMax() += localPos[0];
359 absoluteBB.yMin() += localPos[1];
360 absoluteBB.yMax() += localPos[1];
361 absoluteBB.zMin() += localPos[2];
362 absoluteBB.zMax() += localPos[2];
363
364 if (reference && !reference->isAxisAligned()) { // copy coordinate system
365
366 std::vector<Kernel::V3D> coordSystem;
367 coordSystem.assign(reference->getCoordSystem().begin(), reference->getCoordSystem().end());
368
369 // realign to reference coordinate system
370 absoluteBB.realign(&coordSystem);
371 }
372 return absoluteBB;
373 }
374}
375
387BoundingBox ComponentInfo::boundingBox(const size_t componentIndex, const BoundingBox *reference,
388 const bool excludeMonitors) const {
389 if (isDetector(componentIndex) || componentType(componentIndex) == Beamline::ComponentType::Infinite) {
390 return componentBoundingBox(componentIndex, reference, excludeMonitors);
391 }
392
393 BoundingBox absoluteBB;
394 const auto compFlag = componentType(componentIndex);
395
396 auto parentFlag = Beamline::ComponentType::Generic;
397 if (size() > 1)
398 parentFlag = componentType(parent(componentIndex));
399
400 if (hasSource() && componentIndex == source()) {
401 // Do nothing. Source is not considered part of the beamline for bounding
402 // box calculations.
403 } else if (compFlag == Beamline::ComponentType::Unstructured) {
404 for (const auto &childIndex : this->children(componentIndex)) {
405 absoluteBB.grow(boundingBox(childIndex, reference, excludeMonitors));
406 }
407 } else if (compFlag == Beamline::ComponentType::Grid) {
408 for (const auto &childIndex : this->children(componentIndex)) {
409 growBoundingBoxAsRectuangularBank(childIndex, reference, absoluteBB, excludeMonitors);
410 }
411 } else if (compFlag == Beamline::ComponentType::Rectangular || compFlag == Beamline::ComponentType::Structured ||
412 parentFlag == Beamline::ComponentType::Grid) {
413 growBoundingBoxAsRectuangularBank(componentIndex, reference, absoluteBB, excludeMonitors);
414 } else if (compFlag == Beamline::ComponentType::OutlineComposite) {
415 growBoundingBoxAsOutline(componentIndex, reference, absoluteBB, excludeMonitors);
416 } else {
417 // General case
418 absoluteBB.grow(componentBoundingBox(componentIndex, reference, excludeMonitors));
419 }
420 return absoluteBB;
421}
422
423Beamline::ComponentType ComponentInfo::componentType(const size_t componentIndex) const {
424 return m_componentInfo->componentType(componentIndex);
425}
426
427void ComponentInfo::setScanInterval(const std::pair<Types::Core::DateAndTime, Types::Core::DateAndTime> &interval) {
428 m_componentInfo->setScanInterval({interval.first.totalNanoseconds(), interval.second.totalNanoseconds()});
429}
430
431size_t ComponentInfo::scanCount() const { return m_componentInfo->scanCount(); }
432
433void ComponentInfo::merge(const ComponentInfo &other) { m_componentInfo->merge(*other.m_componentInfo); }
434
436
438
440
442
443} // namespace Mantid::Geometry
double position
Definition: GetAllEi.cpp:154
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
Mantid::Kernel::Quat(ComponentInfo::* rotation)(const size_t) const
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
Definition: BoundingBox.h:34
double xMax() const
Return the maximum value of X.
Definition: BoundingBox.h:80
double zMin() const
Return the minimum value of Z.
Definition: BoundingBox.h:86
std::vector< Kernel::V3D > const & getCoordSystem() const
returns the coordinate system to which BB is alighned to;
Definition: BoundingBox.h:118
double zMax() const
Return the maximum value of Z.
Definition: BoundingBox.h:88
double yMax() const
Return the maximum value of Y.
Definition: BoundingBox.h:84
bool isAxisAligned() const
Check if it is normal axis aligned bounding box or not.
Definition: BoundingBox.h:116
double xMin() const
Return the minimum value of X.
Definition: BoundingBox.h:78
double yMin() const
Return the minimum value of Y.
Definition: BoundingBox.h:82
void grow(const BoundingBox &other)
Grow the bounding box so that it also encompasses the given box.
void realign(std::vector< Kernel::V3D > const *const pCS=nullptr)
reallign the BB according to new coordinate system, provided earlier or specified as parameter;
ComponentInfoIterator for random access iteration over ComponentInfo.
ComponentInfo : Provides a component centric view on to the instrument.
Definition: ComponentInfo.h:40
bool hasParent(const size_t componentIndex) const
const ComponentInfoIterator< const ComponentInfo > cend()
BoundingBox componentBoundingBox(const size_t index, const BoundingBox *reference, const bool excludeMonitors=false) const
Calculates the absolute bounding box for the leaf item at index.
size_t indexOfAny(const std::string &name) const
void setRotation(size_t componentIndex, const Kernel::Quat &newRotation)
bool hasDetectors(const size_t componentIndex) const
bool hasEquivalentSource(const ComponentInfo &other) const
size_t parent(const size_t componentIndex) const
Kernel::Quat rotation(const size_t componentIndex) const
std::shared_ptr< const std::unordered_map< Geometry::IComponent *, size_t > > m_compIDToIndex
Map of component ids to indexes.
Definition: ComponentInfo.h:47
void growBoundingBoxAsOutline(size_t index, const Geometry::BoundingBox *reference, Geometry::BoundingBox &mutableBB, const bool excludeMonitors=false) const
Grow the bounding box on the basis that the component described by index has an outline,...
BoundingBox boundingBox(const size_t componentIndex, const BoundingBox *reference=nullptr, const bool excludeMonitors=false) const
Compute the bounding box for the component with componentIndex taking into account all sub components...
double solidAngle(const size_t componentIndex, const Kernel::V3D &observer) const
Kernel::V3D position(const size_t componentIndex) const
const std::vector< size_t > & children(size_t componentIndex) const
std::vector< size_t > componentsInSubtree(size_t componentIndex) const
void merge(const ComponentInfo &other)
bool hasValidShape(const size_t componentIndex) const
size_t indexOf(Geometry::IComponent *id) const
Kernel::V3D sourcePosition() const
ComponentInfoIterator< ComponentInfo > begin()
bool hasEquivalentSample(const ComponentInfo &other) const
void setScaleFactor(const size_t componentIndex, const Kernel::V3D &scaleFactor)
ComponentInfoIterator< ComponentInfo > end()
std::unique_ptr< Beamline::ComponentInfo > m_componentInfo
Pointer to the actual ComponentInfo object (non-wrapping part).
Definition: ComponentInfo.h:43
std::vector< size_t > detectorsInSubtree(size_t componentIndex) const
bool isDetector(const size_t componentIndex) const
bool uniqueName(const std::string &name) const
void growBoundingBoxAsRectuangularBank(size_t index, const Geometry::BoundingBox *reference, Geometry::BoundingBox &mutableBB, const bool excludeMonitors=false) const
Grow the bounding box on the basis that the component described by index is a regular grid in a trape...
std::unique_ptr< ComponentInfo > cloneWithoutDetectorInfo() const
Clone current instance but not the DetectorInfo non-owned parts.
const ComponentInfoIterator< const ComponentInfo > cbegin()
std::shared_ptr< const std::vector< Geometry::IComponent * > > m_componentIds
Collection of component ids.
Definition: ComponentInfo.h:45
Kernel::V3D relativePosition(const size_t componentIndex) const
const std::string & name(const size_t componentIndex) const
Kernel::Quat relativeRotation(const size_t componentIndex) const
void setPosition(size_t componentIndex, const Kernel::V3D &newPosition)
Kernel::V3D samplePosition() const
const Geometry::IObject & shape(const size_t componentIndex) const
void setScanInterval(const std::pair< Types::Core::DateAndTime, Types::Core::DateAndTime > &interval)
QuadrilateralComponent quadrilateralComponent(const size_t componentIndex) const
Beamline::ComponentType componentType(const size_t componentIndex) const
Kernel::V3D scaleFactor(const size_t componentIndex) const
ComponentInfo(const ComponentInfo &other)
Private copy constructor. Do not make public.
base class for Geometric IComponent
Definition: IComponent.h:51
IObject : Interface for geometry objects.
Definition: IObject.h:41
virtual double solidAngle(const Kernel::V3D &observer) const =0
virtual bool hasValidShape() const =0
Exception thrown when an attempt is made to dereference a null pointer.
Definition: Exception.h:305
Class for quaternions.
Definition: Quat.h:39
Class for 3D vectors.
Definition: V3D.h:34
ComponentInfoIterator< const ComponentInfo > ComponentInfoConstIt
ComponentInfoIterator< ComponentInfo > ComponentInfoIt
Kernel::Quat toQuat(const Eigen::Quaterniond &quat)
Converts Eigen::Quaterniond to Kernel::Quat.
Eigen::Vector3d toVector3d(const Kernel::V3D &vec)
Converts Kernel::V3D to Eigen::Vector3d.
Kernel::V3D toV3D(const Eigen::Vector3d &vec)
This header provides conversion helpers between vector and rotation types in MantidKernel and equival...
Eigen::Quaterniond toQuaterniond(const Kernel::Quat &quat)
Converts Kernel::Quat to Eigen::Quaterniond.
STL namespace.