ObjComponentTest.h 20.1 KB
Newer Older
Russell Taylor's avatar
Russell Taylor committed
1
2
3
4
#ifndef MANTID_TESTOBJCOMPNENT__
#define MANTID_TESTOBJCOMPNENT__

#include <cxxtest/TestSuite.h>
Nick Draper's avatar
re #843    
Nick Draper committed
5
6
7
8
9
#include "MantidGeometry/Instrument/ObjComponent.h"
#include "MantidGeometry/Surfaces/Quadratic.h"
#include "MantidGeometry/Surfaces/Sphere.h"
#include "MantidGeometry/Surfaces/Cylinder.h"
#include "MantidGeometry/Surfaces/Plane.h"
10
#include "MantidGeometry/Objects/CSGObject.h"
Simon Heybrock's avatar
Simon Heybrock committed
11
#include "MantidGeometry/Objects/Track.h"
Russell Taylor's avatar
Russell Taylor committed
12
13
#include "MantidKernel/Exception.h"

14
15
#include "MantidKernel/Timer.h"

16
17
#include "boost/make_shared.hpp"

Russell Taylor's avatar
Russell Taylor committed
18
19
20
using namespace Mantid::Kernel;
using namespace Mantid::Geometry;

21
class ObjComponentTest : public CxxTest::TestSuite {
Russell Taylor's avatar
Russell Taylor committed
22
public:
23
  void testNameConstructor() {
Russell Taylor's avatar
Russell Taylor committed
24
    ObjComponent objComp("objComp1");
25
    TS_ASSERT_EQUALS(objComp.getName(), "objComp1");
Russell Taylor's avatar
Russell Taylor committed
26
27
28
    TS_ASSERT(!objComp.getParent());
  }

29
  void testNameParentConstructor() {
Russell Taylor's avatar
Russell Taylor committed
30
31
    Component parent("Parent");
    ObjComponent objComp("objComp1", &parent);
32
    TS_ASSERT_EQUALS(objComp.getName(), "objComp1");
Russell Taylor's avatar
Russell Taylor committed
33
34
35
    TS_ASSERT(objComp.getParent());
  }

36
  void testType() {
Russell Taylor's avatar
Russell Taylor committed
37
    ObjComponent objComp("objComp");
38
    TS_ASSERT_EQUALS(objComp.type(), "PhysicalComponent");
Russell Taylor's avatar
Russell Taylor committed
39
40
  }

41
  void testShape() {
42
    // Create an empty shape and put it in an ObjComponent
43
    Object_const_sptr shape(new CSGObject);
44
    ObjComponent objComp("obj", shape);
45
    // Get it back - it's the same one
46
    TS_ASSERT_EQUALS(objComp.shape(), shape);
47
    // Put a different shape object in there and check we get back that one
48
    Object_const_sptr shape2(new CSGObject);
49
    objComp.setShape(shape2);
50
51
    TS_ASSERT_DIFFERS(objComp.shape(), shape);
    TS_ASSERT_EQUALS(objComp.shape(), shape2);
52
53
  }

54
  void testIsValid() {
Russell Taylor's avatar
Russell Taylor committed
55
    ObjComponent ocyl("ocyl", createCappedCylinder());
56

57
58
    ocyl.setPos(10, 0, 0);
    ocyl.setRot(Quat(90.0, V3D(0, 0, 1)));
Russell Taylor's avatar
Russell Taylor committed
59
    // Check centre point
60
61
62
63
    TS_ASSERT(ocyl.isValid(V3D(10, 0, 0)));
    // Check a point that wouldn't be inside if the cylinder isn't rotated
    // correctly
    TS_ASSERT(ocyl.isValid(V3D(10, -2.5, 0)));
64
    // Check that a point is not inside, that would be if no rotation
65
    TS_ASSERT(!ocyl.isValid(V3D(11, 0, 0)));
66
    // Now add a parent with a rotation of its own;
67
    Component parent("parent", V3D(0, 10, 0), Quat(90.0, V3D(0, 1, 0)));
Russell Taylor's avatar
Russell Taylor committed
68
    ocyl.setParent(&parent);
69

Russell Taylor's avatar
Russell Taylor committed
70
    // Check centre point
71
72
73
74
75
    TS_ASSERT(ocyl.isValid(V3D(0, 10, -10)));
    // Check a point that wouldn't be inside if the cylinder isn't rotated
    // correctly
    TS_ASSERT(ocyl.isValid(V3D(0, 11.1, -10.5)));
    TS_ASSERT(ocyl.isValid(V3D(0.5, 7, -10)));
76
    // Check that a point is not inside, that would be if no rotation
77
78
79
80
81
    TS_ASSERT(!ocyl.isValid(V3D(0, 10, -11.1)));
    TS_ASSERT(!ocyl.isValid(V3D(1, 10, -10)));
    // Take out component's rotation - it should make no difference because it's
    // about the cylinder axis
    ocyl.setRot(Quat(1, 0, 0, 0));
Russell Taylor's avatar
Russell Taylor committed
82
    // and repeat tests above
83
84
85
86
87
88
89
90
    TS_ASSERT(ocyl.isValid(V3D(0, 10, -10)));
    TS_ASSERT(ocyl.isValid(V3D(0, 10.5, -11.1)));
    TS_ASSERT(ocyl.isValid(V3D(0.5, 10, -7)));
    TS_ASSERT(!ocyl.isValid(V3D(0, 11.1, -10)));
    TS_ASSERT(!ocyl.isValid(V3D(1, 10, -10)));

    // An ObjComponent without an associated geometric object is regarded as a
    // point
91
    ObjComponent comp("noShape");
92
    comp.setPos(1, 2, 3);
Russell Taylor's avatar
Russell Taylor committed
93
    // Check the exact point passes
94
    TS_ASSERT(comp.isValid(V3D(1, 2, 3)));
95
    // But that slightly off fails
96
    TS_ASSERT(!comp.isValid(V3D(1.0001, 2, 3)));
Russell Taylor's avatar
Russell Taylor committed
97
98
  }

99
  void testIsOnSide() {
Russell Taylor's avatar
Russell Taylor committed
100
    ObjComponent ocyl("ocyl", createCappedCylinder());
101
102
103
104
105
106
107
108
109
    ocyl.setPos(10, 0, 0);
    ocyl.setRot(Quat(90.0, V3D(0, 0, 1)));
    TS_ASSERT(ocyl.isOnSide(V3D(10.5, 0, 0)));
    TS_ASSERT(ocyl.isOnSide(V3D(9.5, 0, 0)));
    TS_ASSERT(ocyl.isOnSide(V3D(10, 1, 0.5)));
    TS_ASSERT(ocyl.isOnSide(V3D(10, -3, -0.5)));
    TS_ASSERT(ocyl.isOnSide(V3D(9.7, 1.2, 0.3)));
    TS_ASSERT(ocyl.isOnSide(V3D(10, -3.2, 0)));
    TS_ASSERT(!ocyl.isOnSide(V3D(0, 0, 0)));
110
    // Now add a parent with a rotation of its own;
111
    Component parent("parent", V3D(0, 10, 0), Quat(90.0, V3D(0, 1, 0)));
Russell Taylor's avatar
Russell Taylor committed
112
    ocyl.setParent(&parent);
113
114
115
116
117
118
119
120
121
122
    TS_ASSERT(ocyl.isOnSide(V3D(0.5, 10, -10)));
    TS_ASSERT(ocyl.isOnSide(V3D(0, 9, -10.5)));
    TS_ASSERT(ocyl.isOnSide(V3D(0, 11.2, -10)));
    TS_ASSERT(ocyl.isOnSide(V3D(0.2, 6.8, -9.6)));
    TS_ASSERT(ocyl.isOnSide(V3D(-0.5, 11.2, -10)));
    TS_ASSERT(ocyl.isOnSide(V3D(0, 6.8, -9.5)));
    TS_ASSERT(!ocyl.isOnSide(V3D(0, 0, 0)));
    // Take out component's rotation - it should make no difference because it's
    // about the cylinder axis
    ocyl.setRot(Quat(1, 0, 0, 0));
Russell Taylor's avatar
Russell Taylor committed
123
    // and repeat tests above
124
125
126
127
128
129
130
131
132
133
    TS_ASSERT(ocyl.isOnSide(V3D(0.5, 10, -10)));
    TS_ASSERT(ocyl.isOnSide(V3D(0, 10.5, -9)));
    TS_ASSERT(ocyl.isOnSide(V3D(0, 10, -11.2)));
    TS_ASSERT(ocyl.isOnSide(V3D(0.2, 9.6, -6.8)));
    TS_ASSERT(ocyl.isOnSide(V3D(-0.5, 10, -11.2)));
    TS_ASSERT(ocyl.isOnSide(V3D(0, 9.5, -6.8)));
    TS_ASSERT(!ocyl.isOnSide(V3D(0, 0, 0)));

    // An ObjComponent without an associated geometric object is regarded as a
    // point
134
    ObjComponent comp("noShape");
135
    comp.setPos(1, 2, 3);
Russell Taylor's avatar
Russell Taylor committed
136
    // Check the exact point passes
137
    TS_ASSERT(comp.isOnSide(V3D(1, 2, 3)));
138
    // But that slightly off fails
139
    TS_ASSERT(!comp.isOnSide(V3D(1.0001, 2, 3)));
Russell Taylor's avatar
Russell Taylor committed
140
141
  }

142
  void testInterceptSurface() {
Russell Taylor's avatar
Russell Taylor committed
143
    ObjComponent ocyl("ocyl", createCappedCylinder());
144
145
146
    ocyl.setPos(10, 0, 0);
    ocyl.setRot(Quat(90.0, V3D(0, 0, 1)));
    Track track(V3D(0, 0, 0), V3D(1, 0, 0));
Russell Taylor's avatar
Russell Taylor committed
147

148
    TS_ASSERT_EQUALS(ocyl.interceptSurface(track), 1);
149
150
    Track::LType::const_iterator it = track.cbegin();
    if (it == track.cend())
151
152
153
154
155
      return;
    TS_ASSERT_EQUALS(it->distFromStart, 10.5);
    TS_ASSERT_DELTA(it->distInsideObject, 1, 0.0001);
    TS_ASSERT_EQUALS(it->entryPoint, V3D(9.5, 0, 0));
    TS_ASSERT_EQUALS(it->exitPoint, V3D(10.5, 0, 0));
156
    // Now add a parent with a rotation of its own;
157
    Component parent("parent", V3D(0, 10, 0), Quat(90.0, V3D(0, 1, 0)));
Russell Taylor's avatar
Russell Taylor committed
158
159
    ocyl.setParent(&parent);
    // Check original track misses
160
    TS_ASSERT_EQUALS(ocyl.interceptSurface(track), 0);
161
    // Create a new test track going from the origin down the line y = -x
162
163
    Track track2(V3D(0, 0, 0), V3D(0, 1, -1));
    TS_ASSERT_EQUALS(ocyl.interceptSurface(track2), 1);
164
165
    Track::LType::const_iterator it2 = track2.cbegin();
    if (it2 == track2.cend())
166
167
      return;
    TS_ASSERT_DELTA(it2->distFromStart, sqrt(2 * 10.5 * 10.5), 0.0001);
168
    TS_ASSERT_DELTA(it2->distInsideObject, M_SQRT2, 0.0001);
169
170
171
172
173
    TS_ASSERT_EQUALS(it2->entryPoint, V3D(0, 9.5, -9.5));
    TS_ASSERT_EQUALS(it2->exitPoint, V3D(0, 10.5, -10.5));

    // Calling on an ObjComponent without an associated geometric object will
    // throw
174
    ObjComponent comp("noShape");
175
176
    TS_ASSERT_THROWS(comp.interceptSurface(track),
                     Exception::NullPointerException);
Russell Taylor's avatar
Russell Taylor committed
177
178
  }

179
  void testSolidAngleCappedCylinder() {
Russell Taylor's avatar
Russell Taylor committed
180
    ObjComponent A("ocyl", createCappedCylinder());
181
182
183
    A.setPos(10, 0, 0);
    A.setRot(Quat(90.0, V3D(0, 0, 1)));
    double satol = 2e-2; // tolerance for solid angle
Russell Taylor's avatar
Russell Taylor committed
184

185
    TS_ASSERT_DELTA(A.solidAngle(V3D(10, 1.7, 0)), 1.840302, satol);
Russell Taylor's avatar
Russell Taylor committed
186
    // Surface point
187
    TS_ASSERT_DELTA(A.solidAngle(V3D(10, -1, 0.5)), 2 * M_PI, satol);
Russell Taylor's avatar
Russell Taylor committed
188
189

    // Add a parent with a rotation of its own;
190
    Component parent("parent", V3D(0, 10, 0), Quat(90.0, V3D(0, 1, 0)));
Russell Taylor's avatar
Russell Taylor committed
191
192
    A.setParent(&parent);

193
194
195
196
    // See testSolidAngleCappedCylinder in ObjectTest - these tests are a subset
    // of them
    TS_ASSERT_DELTA(A.solidAngle(V3D(0, 11.7, -10)), 1.840302, satol);
    TS_ASSERT_DELTA(A.solidAngle(V3D(0, 6.13333333, -10)), 1.25663708, satol);
Russell Taylor's avatar
Russell Taylor committed
197
    // internal point (should be 4pi)
198
    TS_ASSERT_DELTA(A.solidAngle(V3D(0, 10, -10)), 4 * M_PI, satol);
Russell Taylor's avatar
Russell Taylor committed
199
    // surface point
200
    TS_ASSERT_DELTA(A.solidAngle(V3D(0.5, 10, -10)), 2 * M_PI, satol);
Russell Taylor's avatar
Russell Taylor committed
201

202
203
    // Calling on an ObjComponent without an associated geometric object will
    // throw
Russell Taylor's avatar
Russell Taylor committed
204
    ObjComponent B("noShape");
205
206
    TS_ASSERT_THROWS(B.solidAngle(V3D(1, 2, 3)),
                     Exception::NullPointerException);
Russell Taylor's avatar
Russell Taylor committed
207
  }
208

209
210
211
  void testBoundingBoxCappedCylinder() {
    // Check that getBoundingBox transforms input guess to Object coordinates
    // and
212
213
    // result back to ObjComponent
    ObjComponent A("ocyl", createCappedCylinder());
214
215
    A.setPos(10, 0, 0);
    A.setRot(Quat(90.0, V3D(0, 0, 1)));
216
217
218

    BoundingBox boundingBox;
    A.getBoundingBox(boundingBox);
219
220
221
222
223
224
    TS_ASSERT_DELTA(boundingBox.xMax(), 10.5, 1e-5);
    TS_ASSERT_DELTA(boundingBox.yMax(), 1.2, 1e-5);
    TS_ASSERT_DELTA(boundingBox.zMax(), 0.5, 1e-5);
    TS_ASSERT_DELTA(boundingBox.xMin(), 9.5, 1e-5);
    TS_ASSERT_DELTA(boundingBox.yMin(), -3.2, 1e-5);
    TS_ASSERT_DELTA(boundingBox.zMin(), -0.5, 1e-5);
225
226

    // Add a parent with a rotation of its own;
227
    Component parent("parent", V3D(0, 10, 0), Quat(90.0, V3D(0, 1, 0)));
228
229
230
231
    A.setParent(&parent);
    // note that input values are ignored in this case as cached results used.
    A.getBoundingBox(boundingBox);
    // consistent with the solid angle results
232
233
    TS_ASSERT_DELTA(boundingBox.zMax(), -9.5, 1e-5);
    TS_ASSERT_DELTA(boundingBox.zMin(), -10.5, 1e-5);
234
  }
235
236
237
  void testNAL_BoundingBoxCappedCylinder() {
    // Check that getBoundingBox transforms input guess to Object coordinates
    // and
238
239
    // result back to ObjComponent
    ObjComponent A("ocyl", createCappedCylinder());
240
241
    A.setPos(10, 0, 0);
    A.setRot(Quat(90.0, V3D(0, 0, 1)));
242
243
244

    BoundingBox boundingBox;
    std::vector<V3D> ort(3);
245
246
247
    ort[0] = V3D(0, 0, 1); // x is now old Z
    ort[1] = V3D(1, 0, 0); // y is now old X
    ort[2] = V3D(0, 1, 0); // z is now old Y
248

249
    boundingBox.setBoxAlignment(V3D(10, 0, 0), ort);
250
251
    A.getBoundingBox(boundingBox);

252
253
    TS_ASSERT_DELTA(boundingBox.xMax(), 0.5, 1e-5);
    TS_ASSERT_DELTA(boundingBox.xMin(), -0.5, 1e-5);
254

255
256
    TS_ASSERT_DELTA(boundingBox.yMax(), 0.5, 1e-5);
    TS_ASSERT_DELTA(boundingBox.yMin(), -0.5, 1e-5);
257

258
259
    TS_ASSERT_DELTA(boundingBox.zMax(), 1.2, 1e-5);
    TS_ASSERT_DELTA(boundingBox.zMin(), -3.2, 1e-5);
260
261
  }

262
  void testgetPointInObject() {
Russell Taylor's avatar
Russell Taylor committed
263
264
    // Check that getPointInObject transforms result back to ObjComponent
    ObjComponent A("ocyl", createCappedCylinder());
265
266
    A.setPos(10, 0, 0);
    A.setRot(Quat(90.0, V3D(0, 0, 1)));
Russell Taylor's avatar
Russell Taylor committed
267
    V3D point;
268
269
270
271
    TS_ASSERT_EQUALS(A.getPointInObject(point), 1);
    TS_ASSERT_DELTA(point.X(), 10.0, 1e-6);
    TS_ASSERT_DELTA(point.Y(), 0.0, 1e-6);
    TS_ASSERT_DELTA(point.Z(), 0.0, 1e-6);
Russell Taylor's avatar
Russell Taylor committed
272
    // Add a parent with a rotation/translation of its own;
273
    Component parent("parent", V3D(0, 10, 0), Quat(90.0, V3D(0, 1, 0)));
Russell Taylor's avatar
Russell Taylor committed
274
    A.setParent(&parent);
275
276
277
278
    TS_ASSERT_EQUALS(A.getPointInObject(point), 1);
    TS_ASSERT_DELTA(point.X(), 0.0, 1e-6);
    TS_ASSERT_DELTA(point.Y(), 10.0, 1e-6);
    TS_ASSERT_DELTA(point.Z(), -10.0, 1e-6);
Russell Taylor's avatar
Russell Taylor committed
279
    // Cuboid not on principle axes
280
281
    std::vector<std::string> planes{"px 0.5", "px 1.5",  "py -22",
                                    "py -21", "pz -0.5", "pz 0.5"};
Russell Taylor's avatar
Russell Taylor committed
282
    ObjComponent D("ocube", createCuboid(planes));
283
284
285
286
287
288
    D.setPos(10, 0, 0);
    D.setRot(Quat(90.0, V3D(0, 0, 1)));
    TS_ASSERT_EQUALS(D.getPointInObject(point), 1);
    TS_ASSERT_DELTA(point.X(), 31.5, 1e-6);
    TS_ASSERT_DELTA(point.Y(), 1.0, 1e-6);
    TS_ASSERT_DELTA(point.Z(), 0.0, 1e-6);
Russell Taylor's avatar
Russell Taylor committed
289
    // Add a parent with a rotation/translation of its own;
290
    // Component parent("parent",V3D(0,10,0),Quat(90.0,V3D(0,1,0)));
Russell Taylor's avatar
Russell Taylor committed
291
    D.setParent(&parent);
292
293
294
295
    TS_ASSERT_EQUALS(D.getPointInObject(point), 1);
    TS_ASSERT_DELTA(point.X(), 0, 1e-6);
    TS_ASSERT_DELTA(point.Y(), 11., 1e-6);
    TS_ASSERT_DELTA(point.Z(), -31.5, 1e-6);
Russell Taylor's avatar
Russell Taylor committed
296
297
  }

298
299
300
301
302
  ObjComponent *MakeWithScaleFactor(const ObjComponent *parent,
                                    ParameterMap *map, double X, double Y,
                                    double Z) {
    ObjComponent *ret = new ObjComponent(parent, map);
    map->addV3D(ret, "sca", V3D(X, Y, Z));
303
304
305
    return ret;
  }

306
  void testIsValidWithScaleFactor() {
307
308
    ParameterMap map;
    ObjComponent ocyl_base("ocyl", createCappedCylinder());
309
310
311
312
313
314
315
    ObjComponent *ocyl = MakeWithScaleFactor(&ocyl_base, &map, 2.0, 1.0, 1.0);
    TS_ASSERT(ocyl->isValid(V3D(2.4, 0.0, 0.0)));
    TS_ASSERT(ocyl->isValid(V3D(-6.4, 0.0, 0.0)));
    TS_ASSERT(!ocyl->isValid(V3D(2.5, 0.0, 0.0)));
    TS_ASSERT(!ocyl->isValid(V3D(-6.5, 0.0, 0.0)));
    TS_ASSERT(ocyl->isValid(V3D(2.3, 0.0, 0.0)));
    TS_ASSERT(ocyl->isValid(V3D(-6.3, 0.0, 0.0)));
316
    delete ocyl;
Russell Taylor's avatar
Russell Taylor committed
317
318
  }

319
  void testIsOnSideWithScaleFactor() {
320
321
    ParameterMap map;
    ObjComponent ocyl_base("ocyl", createCappedCylinder());
322
323
324
325
326
327
328
    ObjComponent *ocyl = MakeWithScaleFactor(&ocyl_base, &map, 2.0, 1.0, 1.0);
    TS_ASSERT(ocyl->isOnSide(V3D(2.4, 0.0, 0.0)));
    TS_ASSERT(ocyl->isOnSide(V3D(-6.4, 0.0, 0.0)));
    TS_ASSERT(!ocyl->isOnSide(V3D(2.5, 0.0, 0.0)));
    TS_ASSERT(!ocyl->isOnSide(V3D(-6.5, 0.0, 0.0)));
    TS_ASSERT(!ocyl->isOnSide(V3D(2.3, 0.0, 0.0)));
    TS_ASSERT(!ocyl->isOnSide(V3D(-6.3, 0.0, 0.0)));
329
    delete ocyl;
Russell Taylor's avatar
Russell Taylor committed
330
331
  }

332
  void testInterceptSurfaceWithScaleFactor() {
333
334
    ParameterMap map;
    ObjComponent ocyl_base("ocyl", createCappedCylinder());
335
    ObjComponent *ocyl = MakeWithScaleFactor(&ocyl_base, &map, 2.0, 1.0, 3.0);
336

337
338
    Track trackScale(V3D(-6.5, 0, 0), V3D(1.0, 0, 0));
    TS_ASSERT_EQUALS(ocyl->interceptSurface(trackScale), 1);
339
    Track::LType::const_iterator itscale = trackScale.cbegin();
340
    TS_ASSERT_EQUALS(itscale->distFromStart, 8.9);
341
342
    TS_ASSERT_EQUALS(itscale->entryPoint, V3D(-6.4, 0.0, 0.0));
    TS_ASSERT_EQUALS(itscale->exitPoint, V3D(2.4, 0.0, 0.0));
343

344
345
    Track trackScaleY(V3D(0.0, -2, 0), V3D(0, 2.0, 0));
    TS_ASSERT_EQUALS(ocyl->interceptSurface(trackScaleY), 1);
346
    Track::LType::const_iterator itscaleY = trackScaleY.cbegin();
347
    TS_ASSERT_EQUALS(itscaleY->distFromStart, 2.5);
348
349
    TS_ASSERT_EQUALS(itscaleY->entryPoint, V3D(0.0, -0.5, 0.0));
    TS_ASSERT_EQUALS(itscaleY->exitPoint, V3D(0.0, 0.5, 0.0));
350

351
352
    Track trackScaleW(V3D(0, 0, -5), V3D(0, 0, 5));
    TS_ASSERT_EQUALS(ocyl->interceptSurface(trackScaleW), 1);
353
    Track::LType::const_iterator itscaleW = trackScaleW.cbegin();
354
    TS_ASSERT_DELTA(itscaleW->distFromStart, 6.5, 1e-6);
355
356
    TS_ASSERT_EQUALS(itscaleW->entryPoint, V3D(0, 0, -1.5));
    TS_ASSERT_EQUALS(itscaleW->exitPoint, V3D(0, 0, +1.5));
357
    delete ocyl;
Russell Taylor's avatar
Russell Taylor committed
358
359
  }

360
  void testBoundingBoxWithScaleFactor() {
361
362
    ParameterMap map;
    ObjComponent A_base("ocyl", createCappedCylinder());
363
    ObjComponent *A = MakeWithScaleFactor(&A_base, &map, 2.0, 1.0, 1.0);
364
365
    BoundingBox bbox;
    A->getBoundingBox(bbox);
366
367
    TS_ASSERT_DELTA(bbox.xMax(), 2.4, 0.00001);
    TS_ASSERT_DELTA(bbox.xMin(), -6.4, 0.00001);
368
    delete A;
Russell Taylor's avatar
Russell Taylor committed
369
370
  }

371
  void testPointInObjectWithScaleFactor() {
372
373
    ParameterMap map;
    ObjComponent A_base("ocyl", createCappedCylinder());
374
    ObjComponent *A = MakeWithScaleFactor(&A_base, &map, 2.0, 1.0, 1.0);
375
    V3D scalept;
376
377
378
379
    TS_ASSERT_EQUALS(A->getPointInObject(scalept), 1);
    TS_ASSERT_DELTA(scalept.X(), 0.0, 1e-6);
    TS_ASSERT_DELTA(scalept.Y(), 0.0, 1e-6);
    TS_ASSERT_DELTA(scalept.Z(), 0.0, 1e-6);
380
    delete A;
Russell Taylor's avatar
Russell Taylor committed
381
382
  }

383
  void testPointInObjectWithScaleFactor2() {
384
385
    ParameterMap map;
    ObjComponent A_base("ocyl", createCappedCylinder());
386
387
388
389
390
391
392
    A_base.setRot(Quat(90.0, V3D(0, 0, 1)));
    ObjComponent *A = MakeWithScaleFactor(&A_base, &map, 2.0, 1.0, 1.0);
    V3D scalept(0, 0, 0);
    TS_ASSERT_EQUALS(A->getPointInObject(scalept), 1);
    TS_ASSERT_DELTA(scalept.X(), 0.0, 1e-6);
    TS_ASSERT_DELTA(scalept.Y(), 0.0, 1e-6);
    TS_ASSERT_DELTA(scalept.Z(), 0.0, 1e-6);
393
    delete A;
394
395
  }

396
  void testPointInObjectWithScaleFactorAndWithOffset() {
397
398
    ParameterMap map;
    ObjComponent A_base("ocyl", createCappedCylinder());
399
400
401
402
403
404
405
    A_base.setPos(10, 0, 0);
    ObjComponent *A = MakeWithScaleFactor(&A_base, &map, 2.0, 1.0, 1.0);
    V3D scalept(0, 0, 0);
    TS_ASSERT_EQUALS(A->getPointInObject(scalept), 1);
    TS_ASSERT_DELTA(scalept.X(), 10.0, 1e-6);
    TS_ASSERT_DELTA(scalept.Y(), 0.0, 1e-6);
    TS_ASSERT_DELTA(scalept.Z(), 0.0, 1e-6);
406
    delete A;
407
408
  }

409
  void testSolidAngleCappedCylinderWithScaleFactor() {
410
411
    ParameterMap map;
    ObjComponent A_base("ocyl", createCappedCylinder());
412
    ObjComponent *A = MakeWithScaleFactor(&A_base, &map, 2.0, 1.0, 1.0);
Russell Taylor's avatar
Russell Taylor committed
413

414
415
416
    A_base.setPos(10, 0, 0);
    A_base.setRot(Quat(90.0, V3D(0, 0, 1)));
    double satol = 3e-3; // tolerance for solid angle
Russell Taylor's avatar
Russell Taylor committed
417
418

    // this point should be 0.5 above the cylinder on its axis of sym
419
    TS_ASSERT_DELTA(A->solidAngle(V3D(10, 2.9, 0)), 1.840302, satol);
420
    // Surface point on the edge of cylinder
421
    TS_ASSERT_DELTA(A->solidAngle(V3D(10, 2.4001, 0)), 2 * M_PI, 1e-2);
422
    // Internal point
423
    TS_ASSERT_DELTA(A->solidAngle(V3D(10, 0, 0)), 4 * M_PI, satol);
Russell Taylor's avatar
Russell Taylor committed
424
425

    // Add a parent with a rotation of its own;
426
    Component parent("parent", V3D(0, 10, 0), Quat(0.0, V3D(0, 1, 0)));
427
    A_base.setParent(&parent);
Russell Taylor's avatar
Russell Taylor committed
428

429
430
    // See testSolidAngleCappedCylinder in ObjectTest - these tests are a subset
    // of them
Russell Taylor's avatar
Russell Taylor committed
431
    // assume this is the same position as above
432
    TS_ASSERT_DELTA(A->solidAngle(V3D(10, 12.9, 0)), 1.840302, satol);
Russell Taylor's avatar
Russell Taylor committed
433
    // internal point (should be 4pi)
434
    TS_ASSERT_DELTA(A->solidAngle(V3D(10, 10, 0)), 4 * M_PI, satol);
Russell Taylor's avatar
Russell Taylor committed
435

436
437
    // Calling on an ObjComponent without an associated geometric object will
    // throw
Russell Taylor's avatar
Russell Taylor committed
438
    ObjComponent B("noShape");
439
440
    TS_ASSERT_THROWS(B.solidAngle(V3D(1, 2, 3)),
                     Exception::NullPointerException)
441
    delete A;
Russell Taylor's avatar
Russell Taylor committed
442
443
444
  }

private:
445
  boost::shared_ptr<CSGObject> createCappedCylinder() {
446
447
448
    std::string C31 = "cx 0.5"; // cylinder x-axis radius 0.5
    std::string C32 = "px 1.2";
    std::string C33 = "px -3.2";
Russell Taylor's avatar
Russell Taylor committed
449
450

    // First create some surfaces
451
452
453
454
    std::map<int, boost::shared_ptr<Surface>> CylSurMap;
    CylSurMap[31] = boost::make_shared<Cylinder>();
    CylSurMap[32] = boost::make_shared<Plane>();
    CylSurMap[33] = boost::make_shared<Plane>();
Russell Taylor's avatar
Russell Taylor committed
455
456
457
458
459
460
461
462
463
464

    CylSurMap[31]->setSurface(C31);
    CylSurMap[32]->setSurface(C32);
    CylSurMap[33]->setSurface(C33);
    CylSurMap[31]->setName(31);
    CylSurMap[32]->setName(32);
    CylSurMap[33]->setName(33);

    // Capped cylinder (id 21)
    // using surface ids: 31 (cylinder) 32 (plane (top) ) and 33 (plane (base))
465
    std::string ObjCapCylinder = "-31 -32 33";
Russell Taylor's avatar
Russell Taylor committed
466

467
    auto retVal = boost::make_shared<CSGObject>();
468
    retVal->setObject(21, ObjCapCylinder);
Russell Taylor's avatar
Russell Taylor committed
469
470
471
472
473
    retVal->populate(CylSurMap);

    return retVal;
  }

474
  boost::shared_ptr<CSGObject> createCappedCylinder2() {
475
476
477
    std::string C31 = "cx 0.5"; // cylinder x-axis radius 0.5
    std::string C32 = "px -1.0";
    std::string C33 = "px -3.0";
478
479

    // First create some surfaces
480
481
482
483
    std::map<int, boost::shared_ptr<Surface>> CylSurMap;
    CylSurMap[31] = boost::make_shared<Cylinder>();
    CylSurMap[32] = boost::make_shared<Plane>();
    CylSurMap[33] = boost::make_shared<Plane>();
484
485
486
487
488
489
490
491
492
493

    CylSurMap[31]->setSurface(C31);
    CylSurMap[32]->setSurface(C32);
    CylSurMap[33]->setSurface(C33);
    CylSurMap[31]->setName(31);
    CylSurMap[32]->setName(32);
    CylSurMap[33]->setName(33);

    // Capped cylinder (id 21)
    // using surface ids: 31 (cylinder) 32 (plane (top) ) and 33 (plane (base))
494
    std::string ObjCapCylinder = "-31 -32 33";
495

496
    boost::shared_ptr<CSGObject> retVal = boost::make_shared<CSGObject>();
497
    retVal->setObject(21, ObjCapCylinder);
498
499
500
501
502
    retVal->populate(CylSurMap);

    return retVal;
  }

503
  boost::shared_ptr<CSGObject> createCuboid(std::vector<std::string> &planes) {
504
505
506
507
508
509
    std::string C1 = planes[0];
    std::string C2 = planes[1];
    std::string C3 = planes[2];
    std::string C4 = planes[3];
    std::string C5 = planes[4];
    std::string C6 = planes[5];
Russell Taylor's avatar
Russell Taylor committed
510
511

    // Create surfaces
512
513
514
515
516
517
518
    std::map<int, boost::shared_ptr<Surface>> CubeSurMap;
    CubeSurMap[1] = boost::make_shared<Plane>();
    CubeSurMap[2] = boost::make_shared<Plane>();
    CubeSurMap[3] = boost::make_shared<Plane>();
    CubeSurMap[4] = boost::make_shared<Plane>();
    CubeSurMap[5] = boost::make_shared<Plane>();
    CubeSurMap[6] = boost::make_shared<Plane>();
Russell Taylor's avatar
Russell Taylor committed
519
520
521
522
523
524
525
526
527
528
529
530
531
532

    CubeSurMap[1]->setSurface(C1);
    CubeSurMap[2]->setSurface(C2);
    CubeSurMap[3]->setSurface(C3);
    CubeSurMap[4]->setSurface(C4);
    CubeSurMap[5]->setSurface(C5);
    CubeSurMap[6]->setSurface(C6);
    CubeSurMap[1]->setName(1);
    CubeSurMap[2]->setName(2);
    CubeSurMap[3]->setName(3);
    CubeSurMap[4]->setName(4);
    CubeSurMap[5]->setName(5);
    CubeSurMap[6]->setName(6);

533
    // Cube (id 68)
Russell Taylor's avatar
Russell Taylor committed
534
    // using surface ids:  1-6
535
    std::string ObjCube = "1 -2 3 -4 5 -6";
Russell Taylor's avatar
Russell Taylor committed
536

537
    boost::shared_ptr<CSGObject> retVal = boost::make_shared<CSGObject>();
538
    retVal->setObject(68, ObjCube);
Russell Taylor's avatar
Russell Taylor committed
539
540
541
542
543
544
545
    retVal->populate(CubeSurMap);

    return retVal;
  }
};

#endif