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 const *, 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
129size_t ComponentInfo::indexOf(Geometry::IComponent const *id) const { return m_compIDToIndex->at(id); }
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 *shapeAtIndex = (*m_shapes)[componentIndex].get();
141 return shapeAtIndex != nullptr && shapeAtIndex->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
176void ComponentInfo::scaleComponent(const size_t componentIndex, const Kernel::V3D &newScaling) {
177 m_componentInfo->scaleComponent(componentIndex, Kernel::toVector3d(newScaling));
178}
179
180void ComponentInfo::scaleComponent(const std::pair<size_t, size_t> &index, const Kernel::V3D &newScaling) {
181 m_componentInfo->scaleComponent(index, Kernel::toVector3d(newScaling));
182}
183
184size_t ComponentInfo::parent(const size_t componentIndex) const { return m_componentInfo->parent(componentIndex); }
185
186bool ComponentInfo::hasParent(const size_t componentIndex) const { return m_componentInfo->hasParent(componentIndex); }
187
188bool ComponentInfo::hasDetectorInfo() const { return m_componentInfo->hasDetectorInfo(); }
189
191
193
194bool ComponentInfo::hasSource() const { return m_componentInfo->hasSource(); }
195
196/*
197 * @brief Check the sources of two componentInfo objects coincide
198 *
199 * @details check both objects either lack or have a source. If the latter,
200 * check their positions differ by less than 1 nm = 1e-9 m.
201 *
202 * @returns true if sources are equivalent
203 */
205 return m_componentInfo->hasEquivalentSource(*(other.m_componentInfo));
206}
207
208bool ComponentInfo::hasSample() const { return m_componentInfo->hasSample(); }
209
210/*
211 * @brief Check the samples of two componentInfo objects coincide
212 *
213 * @details check both objects either lack or have a sample. If the latter,
214 * check their positions differ by less than 1 nm = 1e-9 m.
215 *
216 * @returns true if sources are equivalent
217 */
219 return m_componentInfo->hasEquivalentSample(*(other.m_componentInfo));
220}
221
222bool ComponentInfo::hasDetectors(const size_t componentIndex) const {
223 if (isDetector(componentIndex))
224 return false;
225 const auto range = m_componentInfo->detectorRangeInSubtree(componentIndex);
226 return range.begin() < range.end();
227}
228
229size_t ComponentInfo::source() const { return m_componentInfo->source(); }
230
231size_t ComponentInfo::sample() const { return m_componentInfo->sample(); }
232
233double ComponentInfo::l1() const { return m_componentInfo->l1(); }
234
235size_t ComponentInfo::root() const { return m_componentInfo->root(); }
236
237void ComponentInfo::setPosition(const size_t componentIndex, const Kernel::V3D &newPosition) {
238 m_componentInfo->setPosition(componentIndex, Kernel::toVector3d(newPosition));
239}
240
241void ComponentInfo::setRotation(const size_t componentIndex, const Kernel::Quat &newRotation) {
242 m_componentInfo->setRotation(componentIndex, Kernel::toQuaterniond(newRotation));
243}
244
245const IObject &ComponentInfo::shape(const size_t componentIndex) const { return *(*m_shapes)[componentIndex]; }
246
247Kernel::V3D ComponentInfo::scaleFactor(const size_t componentIndex) const {
248 return Kernel::toV3D(m_componentInfo->scaleFactor(componentIndex));
249}
250
251const std::string &ComponentInfo::name(const size_t componentIndex) const {
252 return m_componentInfo->name(componentIndex);
253}
254
255void ComponentInfo::setScaleFactor(const size_t componentIndex, const Kernel::V3D &scaleFactor) {
256 m_componentInfo->setScaleFactor(componentIndex, Kernel::toVector3d(scaleFactor));
257}
258
259double ComponentInfo::solidAngle(const size_t componentIndex, const Geometry::SolidAngleParams &params) const {
260 if (!hasValidShape(componentIndex))
261 throw Kernel::Exception::NullPointerException("ComponentInfo::solidAngle", "shape");
262 // This is the observer position in the shape's coordinate system.
263 const Kernel::V3D relativeObserver = toShapeFrame(params.observer(), *m_componentInfo, componentIndex);
264 const Kernel::V3D scaleFactorAtIndex = this->scaleFactor(componentIndex);
265 const auto paramsWithRelativeObserver = params.copyWithNewObserver(relativeObserver);
266 if ((scaleFactorAtIndex - Kernel::V3D(1.0, 1.0, 1.0)).norm() < 1e-12)
267 return shape(componentIndex).solidAngle(paramsWithRelativeObserver);
268 else {
269 // This function will scale the object shape when calculating the solid
270 // angle.
271 return shape(componentIndex).solidAngle(paramsWithRelativeObserver, scaleFactorAtIndex);
272 }
273}
274
293 Geometry::BoundingBox &mutableBB,
294 const bool excludeMonitors) const {
295
296 auto panel = quadrilateralComponent(index);
297 mutableBB.grow(componentBoundingBox(panel.bottomLeft, reference, excludeMonitors));
298 mutableBB.grow(componentBoundingBox(panel.topRight, reference, excludeMonitors));
299 mutableBB.grow(componentBoundingBox(panel.topLeft, reference, excludeMonitors));
300 mutableBB.grow(componentBoundingBox(panel.bottomRight, reference, excludeMonitors));
301}
302
314 const bool excludeMonitors) const {
315 mutableBB.grow(componentBoundingBox(index, reference, excludeMonitors));
316}
317
328 const bool excludeMonitors) const {
329 // Check that we have a valid shape here
330 if (componentType(index) == Beamline::ComponentType::Infinite) {
331 return BoundingBox(); // Return null bounding box
332 }
333 if (excludeMonitors) {
334 // skip monitors
335 if (isDetector(index) && m_componentInfo->isMonitor(index)) {
336 return BoundingBox();
337 }
338 // skip other components such as choppers, etc
339 if (componentType(index) == Beamline::ComponentType::Generic) {
340 return BoundingBox();
341 }
342 }
343 if (!hasValidShape(index)) {
344 return BoundingBox(this->position(index).X(), this->position(index).Y(), this->position(index).Z(),
345 this->position(index).X(), this->position(index).Y(), this->position(index).Z());
346 } else {
347 const auto &s = this->shape(index);
348 BoundingBox absoluteBB = s.getBoundingBox();
349
350 // modify in place for speed
351 const Eigen::Vector3d scaleFactorAtIndex = m_componentInfo->scaleFactor(index);
352 // Scale
353 absoluteBB.xMin() *= scaleFactorAtIndex[0];
354 absoluteBB.xMax() *= scaleFactorAtIndex[0];
355 absoluteBB.yMin() *= scaleFactorAtIndex[1];
356 absoluteBB.yMax() *= scaleFactorAtIndex[1];
357 absoluteBB.zMin() *= scaleFactorAtIndex[2];
358 absoluteBB.zMax() *= scaleFactorAtIndex[2];
359 // Rotate
360 (this->rotation(index))
361 .rotateBB(absoluteBB.xMin(), absoluteBB.yMin(), absoluteBB.zMin(), absoluteBB.xMax(), absoluteBB.yMax(),
362 absoluteBB.zMax());
363
364 // Shift
365 const Eigen::Vector3d localPos = m_componentInfo->position(index);
366 absoluteBB.xMin() += localPos[0];
367 absoluteBB.xMax() += localPos[0];
368 absoluteBB.yMin() += localPos[1];
369 absoluteBB.yMax() += localPos[1];
370 absoluteBB.zMin() += localPos[2];
371 absoluteBB.zMax() += localPos[2];
372
373 if (reference && !reference->isAxisAligned()) { // copy coordinate system
374
375 std::vector<Kernel::V3D> coordSystem;
376 coordSystem.assign(reference->getCoordSystem().begin(), reference->getCoordSystem().end());
377
378 // realign to reference coordinate system
379 absoluteBB.realign(&coordSystem);
380 }
381 return absoluteBB;
382 }
383}
384
396BoundingBox ComponentInfo::boundingBox(const size_t componentIndex, const BoundingBox *reference,
397 const bool excludeMonitors) const {
398 if (isDetector(componentIndex) || componentType(componentIndex) == Beamline::ComponentType::Infinite) {
399 return componentBoundingBox(componentIndex, reference, excludeMonitors);
400 }
401
402 BoundingBox absoluteBB;
403 const auto compFlag = componentType(componentIndex);
404
405 auto parentFlag = Beamline::ComponentType::Generic;
406 if (size() > 1)
407 parentFlag = componentType(parent(componentIndex));
408
409 if (hasSource() && componentIndex == source()) {
410 // Do nothing. Source is not considered part of the beamline for bounding
411 // box calculations.
412 } else if (compFlag == Beamline::ComponentType::Unstructured) {
413 for (const auto &childIndex : this->children(componentIndex)) {
414 absoluteBB.grow(boundingBox(childIndex, reference, excludeMonitors));
415 }
416 } else if (compFlag == Beamline::ComponentType::Grid) {
417 for (const auto &childIndex : this->children(componentIndex)) {
418 growBoundingBoxAsRectuangularBank(childIndex, reference, absoluteBB, excludeMonitors);
419 }
420 } else if (compFlag == Beamline::ComponentType::Rectangular || compFlag == Beamline::ComponentType::Structured ||
421 parentFlag == Beamline::ComponentType::Grid) {
422 growBoundingBoxAsRectuangularBank(componentIndex, reference, absoluteBB, excludeMonitors);
423 } else if (compFlag == Beamline::ComponentType::OutlineComposite) {
424 growBoundingBoxAsOutline(componentIndex, reference, absoluteBB, excludeMonitors);
425 } else {
426 // General case
427 absoluteBB.grow(componentBoundingBox(componentIndex, reference, excludeMonitors));
428 }
429 return absoluteBB;
430}
431
432Beamline::ComponentType ComponentInfo::componentType(const size_t componentIndex) const {
433 return m_componentInfo->componentType(componentIndex);
434}
435
436void ComponentInfo::setScanInterval(const std::pair<Types::Core::DateAndTime, Types::Core::DateAndTime> &interval) {
437 m_componentInfo->setScanInterval({interval.first.totalNanoseconds(), interval.second.totalNanoseconds()});
438}
439
440size_t ComponentInfo::scanCount() const { return m_componentInfo->scanCount(); }
441
442void ComponentInfo::merge(const ComponentInfo &other) { m_componentInfo->merge(*other.m_componentInfo); }
443
445
447
449
451
452} // namespace Mantid::Geometry
std::string name
Definition Run.cpp:60
double position
Definition GetAllEi.cpp:154
std::map< DeltaEMode::Type, std::string > index
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:33
double xMax() const
Return the maximum value of X.
Definition BoundingBox.h:79
double zMin() const
Return the minimum value of Z.
Definition BoundingBox.h:85
std::vector< Kernel::V3D > const & getCoordSystem() const
returns the coordinate system to which BB is alighned to;
double zMax() const
Return the maximum value of Z.
Definition BoundingBox.h:87
double yMax() const
Return the maximum value of Y.
Definition BoundingBox.h:83
bool isAxisAligned() const
Check if it is normal axis aligned bounding box or not.
double xMin() const
Return the minimum value of X.
Definition BoundingBox.h:77
double yMin() const
Return the minimum value of Y.
Definition BoundingBox.h:81
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;
ComponentInfo : Provides a component centric view on to the instrument.
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
double solidAngle(const size_t componentIndex, const Geometry::SolidAngleParams &params) const
size_t parent(const size_t componentIndex) const
Kernel::Quat rotation(const size_t componentIndex) const
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...
void scaleComponent(const size_t componentIndex, const Kernel::V3D &newScaling)
std::shared_ptr< const std::unordered_map< Geometry::IComponent const *, size_t > > m_compIDToIndex
Map of component ids to indexes.
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
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).
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.
Kernel::V3D relativePosition(const size_t componentIndex) const
size_t indexOf(Geometry::IComponent const *id) 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)
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:53
IObject : Interface for geometry objects.
Definition IObject.h:42
virtual double solidAngle(const SolidAngleParams &params) const =0
const SolidAngleParams copyWithNewObserver(Kernel::V3D newObserver) const
const Kernel::V3D & observer() const
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.