Mantid
Loading...
Searching...
No Matches
Track.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 +
10#include "MantidKernel/Matrix.h"
12#include "MantidKernel/V3D.h"
13#include <boost/iterator/distance.hpp>
14
15#include <algorithm>
16#include <cmath>
17
18namespace Mantid::Geometry {
20using Kernel::V3D;
21
25Track::Track() : m_line(V3D(), V3D(0., 0., 1.)) {}
26
32Track::Track(const V3D &startPt, const V3D &unitVector) : m_line(startPt, unitVector) {
33 if (!unitVector.unitVector()) {
34 throw std::invalid_argument("Failed to construct track: direction is not a unit vector.");
35 }
36 m_links.reserve(2);
37 m_surfPoints.reserve(4);
38}
39
45void Track::reset(const V3D &startPoint, const V3D &direction) {
46 if (!direction.unitVector()) {
47 throw std::invalid_argument("Failed to reset track: direction is not a unit vector.");
48 }
50}
51
56 m_links.clear();
57 m_surfPoints.clear();
58}
59
65int Track::nonComplete() const {
66 if (m_links.size() < 2) {
67 return 0;
68 }
69 auto ac = m_links.cbegin();
70 if (m_line.getOrigin().distance(ac->entryPoint) > Tolerance) {
71 return 1;
72 }
73 auto bc = ac;
74 ++bc;
75
76 while (bc != m_links.end()) {
77 if ((ac->exitPoint).distance(bc->entryPoint) > Tolerance) {
78 return (static_cast<int>(boost::distance(m_links.begin(), bc)) + 1);
79 }
80 ++ac;
81 ++bc;
82 }
83 // success
84 return 0;
85}
86
92 if (m_links.empty()) {
93 return;
94 }
95 auto prevNode = m_links.begin();
96 auto nextNode = m_links.begin();
97 ++nextNode;
98 while (nextNode != m_links.end()) {
99 if (prevNode->componentID == nextNode->componentID) {
100 prevNode->exitPoint = nextNode->exitPoint;
101 prevNode->distFromStart = prevNode->entryPoint.distance(prevNode->exitPoint);
102 prevNode->distInsideObject = nextNode->distInsideObject;
103 m_links.erase(nextNode);
104 nextNode = prevNode;
105 ++nextNode;
106 } else {
107 ++prevNode;
108 ++nextNode;
109 }
110 }
111}
112
124void Track::addPoint(const TrackDirection direction, const V3D &endPoint, const IObject &obj,
125 const ComponentID compID) {
126 IntersectionPoint newPoint(direction, endPoint, endPoint.distance(m_line.getOrigin()), obj, compID);
127 if (m_surfPoints.empty()) {
128 m_surfPoints.push_back(newPoint);
129 } else {
130 auto lowestPtr = std::lower_bound(m_surfPoints.begin(), m_surfPoints.end(), newPoint);
131 if (lowestPtr != m_surfPoints.end()) {
132 // Make sure same point isn't added twice
133 if (newPoint == *lowestPtr) {
134 return;
135 }
136 }
137
138 m_surfPoints.insert(lowestPtr, newPoint);
139 }
140}
141
152int Track::addLink(const V3D &firstPoint, const V3D &secondPoint, const double distanceAlongTrack, const IObject &obj,
153 const ComponentID compID) {
154 // Process First Point
155 Link newLink(firstPoint, secondPoint, distanceAlongTrack, obj, compID);
156 int index(0);
157 if (m_links.empty()) {
158 m_links.emplace_back(newLink);
159 index = 0;
160 } else {
161 // Check if the same Link has already been added before adding newLink
162 // This might not be the most efficient method of testing this, but
163 // the similar/identical link is not necessarily the one at the end of
164 // the m_links array.. so we have to loop over and check each
165 for (auto it = m_links.begin(); it != m_links.end(); ++it) {
166 if (newLink == *it) {
167 return static_cast<int>(std::distance(m_links.begin(), m_links.end()));
168 }
169 }
170
171 auto linkPtr = std::lower_bound(m_links.begin(), m_links.end(), newLink);
172 // must extract the distance before you insert otherwise the iterators are
173 // incompatible
174 index = static_cast<int>(std::distance(m_links.begin(), linkPtr));
175 m_links.insert(linkPtr, newLink);
176 }
177 return index;
178}
179
185 if (m_surfPoints.empty()) {
186 return;
187 }
188
189 // The surface points were added in order when they were built so no sorting
190 // is required here.
191 auto ac = m_surfPoints.cbegin();
192 auto bc = ac;
193 ++bc;
194 // First point is not necessarily in an object
195 // Process first point:
196 while (ac != m_surfPoints.end() && ac->direction != TrackDirection::ENTERING) // stepping from an object.
197 {
198 if (ac->direction == TrackDirection::LEAVING) {
199 addLink(m_line.getOrigin(), ac->endPoint, ac->distFromStart, *ac->object,
200 ac->componentID); // from the void
201 }
202 ++ac;
203 if (bc != m_surfPoints.end()) {
204 ++bc;
205 }
206 }
207
208 // have we now passed over all of the potential intersections without actually
209 // hitting the object
210 if (ac == m_surfPoints.end()) {
211 // yes
212 m_surfPoints.clear();
213 return;
214 }
215
216 V3D workPt = ac->endPoint; // last good point
217 while (bc != m_surfPoints.end()) // Since bc > ac
218 {
219 if (ac->direction == TrackDirection::ENTERING && bc->direction == TrackDirection::LEAVING) {
220 // Touching surface / identical surface
221 if (fabs(ac->distFromStart - bc->distFromStart) > Tolerance) {
222 // track leave ac into bc.
223 addLink(ac->endPoint, bc->endPoint, bc->distFromStart, *ac->object, ac->componentID);
224 }
225 // Points with intermediate void
226 else {
227 addLink(workPt, ac->endPoint, ac->distFromStart, *ac->object, ac->componentID);
228 }
229 workPt = bc->endPoint;
230
231 // incrementing ac twice: since processing pairs
232 ++ac;
233 ++ac;
234 ++bc; // can I do this past the end ?
235 if (bc != m_surfPoints.end()) {
236 ++bc;
237 }
238 } else // Test for glancing point / or void edges
239 { // These all can be skipped
240 ++ac;
241 ++bc;
242 }
243 }
244
245 m_surfPoints.clear();
246}
247
255 return std::accumulate(m_links.begin(), m_links.end(), 0.,
256 [](double total, const auto &link) { return total + link.distInsideObject; });
257}
258
259std::ostream &operator<<(std::ostream &os, TrackDirection direction) {
260 switch (direction) {
262 os << "ENTERING";
263 break;
265 os << "LEAVING";
266 break;
268 os << "INVALID";
269 break;
270 default:
271 os.setstate(std::ios_base::failbit);
272 }
273 return os;
274}
275
277 double factor(1.0);
278 for (const auto &segment : m_links) {
279 const double length = segment.distInsideObject;
280 const auto &segObj = *(segment.object);
281 factor *= segObj.material().attenuation(length, lambda);
282 }
283 return factor;
284}
285
286} // namespace Mantid::Geometry
const std::vector< double > * lambda
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
#define fabs(x)
Definition: Matrix.cpp:22
double obj
the value of the quadratic function
base class for Geometric IComponent
Definition: IComponent.h:51
IObject : Interface for geometry objects.
Definition: IObject.h:41
const Kernel::V3D & getOrigin() const
returns the origin
Definition: Line.h:52
int setLine(const Kernel::V3D &, const Kernel::V3D &)
input Origin + direction
Definition: Line.cpp:260
const Kernel::V3D & startPoint() const
Returns the starting point.
Definition: Track.h:191
PType m_surfPoints
Intersection points.
Definition: Track.h:230
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
void removeCojoins()
Remove touching Links that have identical components.
Definition: Track.cpp:91
void addPoint(const TrackDirection direction, const Kernel::V3D &endPoint, const IObject &obj, const ComponentID compID=nullptr)
Adds a point of intersection to the track.
Definition: Track.cpp:124
double totalDistInsideObject() const
Returns the sum of all the links distInsideObject in the track.
Definition: Track.cpp:254
void buildLink()
Construct links between added points.
Definition: Track.cpp:184
const Kernel::V3D & direction() const
Returns the direction as a unit vector.
Definition: Track.h:193
int nonComplete() const
Is the link complete?
Definition: Track.cpp:65
LType m_links
Track units.
Definition: Track.h:229
virtual double calculateAttenuation(double lambda) const
Calculate attenuation across all links.
Definition: Track.cpp:276
Track()
Default constructor.
Definition: Track.cpp:25
void reset(const Kernel::V3D &startPoint, const Kernel::V3D &direction)
Set a starting point and direction.
Definition: Track.cpp:45
Line m_line
Line object containing origin and direction.
Definition: Track.h:228
Class for 3D vectors.
Definition: V3D.h:34
double distance(const V3D &v) const noexcept
Calculates the distance between two vectors.
Definition: V3D.h:287
bool unitVector(const double tolerance=Kernel::Tolerance) const noexcept
Definition: V3D.cpp:251
MANTID_GEOMETRY_DLL std::ostream & operator<<(std::ostream &stream, const PointGroup &self)
Returns a streamed representation of the PointGroup object.
Definition: PointGroup.cpp:312
constexpr double Tolerance
Standard tolerance value.
Definition: Tolerance.h:12
Stores a point of intersection along a track.
Definition: Track.h:106