-
Notifications
You must be signed in to change notification settings - Fork 122
/
ComponentHelper.cpp
166 lines (147 loc) · 5.42 KB
/
ComponentHelper.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "MantidGeometry/Instrument/ComponentHelper.h"
#include "MantidGeometry/Instrument/ParameterMap.h"
#include "MantidGeometry/IComponent.h"
#include "MantidGeometry/Instrument/ReferenceFrame.h"
#include "MantidGeometry/Objects/ShapeFactory.h"
#include "MantidGeometry/Instrument/Detector.h"
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
namespace Mantid {
namespace Geometry {
namespace ComponentHelper {
using Kernel::V3D;
using Kernel::Quat;
/**
* Add/modify an entry in the parameter map for the given component
* to update its position. The component is const
* as the move doesn't actually change the object
* @param comp A reference to the component to move
* @param pmap A reference to the ParameterMap that will hold the new position
* @param pos The new position
* @param positionType Defines how the given position should be interpreted @see
* TransformType enumeration
*/
void moveComponent(const IComponent &comp, ParameterMap &pmap,
const Kernel::V3D &pos, const TransformType positionType) {
//
// This behaviour was copied from how MoveInstrumentComponent worked
//
// First set it to the new absolute position
V3D newPos = pos;
switch (positionType) {
case Absolute: // Do nothing
break;
case Relative:
newPos += comp.getPos();
break;
default:
throw std::invalid_argument("moveComponent - Unknown positionType: " +
boost::lexical_cast<std::string>(positionType));
}
// Then find the corresponding relative position
auto parent = comp.getParent();
if (parent) {
newPos -= parent->getPos();
Quat rot = parent->getRotation();
rot.inverse();
rot.rotate(newPos);
}
// Add a parameter for the new position
pmap.addV3D(comp.getComponentID(), "pos", newPos);
}
/**
* Add/modify an entry in the parameter map for the given component
* to update its rotation. The component is const
* as the move doesn't actually change the object
* @param comp A reference to the component to move
* @param pmap A reference to the ParameterMap that will hold the new position
* @param rot The rotation quaternion
* @param rotType Defines how the given rotation should be interpreted @see
* TransformType enumeration
*/
void rotateComponent(const IComponent &comp, ParameterMap &pmap,
const Kernel::Quat &rot, const TransformType rotType) {
//
// This behaviour was copied from how RotateInstrumentComponent worked
//
Quat newRot = rot;
if (rotType == Absolute) {
// Find the corresponding relative position
auto parent = comp.getParent();
if (parent) {
Quat rot0 = parent->getRelativeRot();
rot0.inverse();
newRot = rot * rot0;
}
} else if (rotType == Relative) {
const Quat &Rot0 = comp.getRelativeRot();
newRot = Rot0 * rot;
} else {
throw std::invalid_argument("rotateComponent - Unknown rotType: " +
boost::lexical_cast<std::string>(rotType));
}
// Add a parameter for the new rotation
pmap.addQuat(comp.getComponentID(), "rot", newRot);
}
/**
* createOneDetectorInstrument, creates the most simple possible definition of an instrument in which we can extract a valid L1 and L2 distance for unit calculations.
*
* Beam direction is along X,
* Up direction is Y
*
* @param sourcePos : V3D position
* @param samplePos : V3D sample position
* @param detectorPos : V3D detector position
* @return Instrument generated.
*/
Geometry::Instrument_sptr createMinimalInstrument(const Mantid::Kernel::V3D& sourcePos, const Mantid::Kernel::V3D& samplePos, const Mantid::Kernel::V3D& detectorPos )
{
Instrument_sptr instrument = boost::make_shared<Instrument>();
instrument->setReferenceFrame(
boost::make_shared<ReferenceFrame>(Mantid::Geometry::Y /*up*/, Mantid::Geometry::X /*along*/, Left, "0,0,0"));
// A source
ObjComponent *source = new ObjComponent("source");
source->setPos(sourcePos);
source->setShape(createSphere(0.01 /*1cm*/, V3D(0,0,0), "1"));
instrument->add(source);
instrument->markAsSource(source);
// A sample
ObjComponent *sample = new ObjComponent("some-surface-holder");
sample->setPos(samplePos);
sample->setShape(createSphere(0.01 /*1cm*/, V3D(0,0,0), "1"));
instrument->add(sample);
instrument->markAsSamplePos(sample);
// A detector
Detector *det = new Detector("point-detector", 1 /*detector id*/, NULL);
det->setPos(detectorPos);
det->setShape(createSphere(0.01 /*1cm*/, V3D(0,0,0), "1"));
instrument->add(det);
instrument->markAsDetector(det);
return instrument;
}
/**
* Create a sphere object
*/
Object_sptr createSphere(double radius, const V3D ¢re,
const std::string &id) {
ShapeFactory shapeMaker;
return shapeMaker.createShape(sphereXML(radius, centre, id));
}
/**
* Return the XML for a sphere.
*/
std::string sphereXML(double radius, const Kernel::V3D ¢re, const std::string &id) {
std::ostringstream xml;
xml << "<sphere id=\"" << id << "\">"
<< "<centre x=\"" << centre.X() << "\" y=\"" << centre.Y() << "\" z=\""
<< centre.Z() << "\" />"
<< "<radius val=\"" << radius << "\" />"
<< "</sphere>";
return xml.str();
}
} // namespace ComponentHelper
}
} // namespace Mantid::Geometry