ObjectTest.h 37.3 KB
Newer Older
Russell Taylor's avatar
Russell Taylor committed
1
2
3
4
5
6
7
8
9
#ifndef MANTID_TESTOBJECT__
#define MANTID_TESTOBJECT__

#include <cxxtest/TestSuite.h>
#include <cmath>
#include <ostream>
#include <vector>
#include <algorithm>
#include <ctime>
10
#include <iomanip>
Russell Taylor's avatar
Russell Taylor committed
11

12
13
#include <boost/shared_ptr.hpp>

14
15
16
17
18
19
20
#include "MantidGeometry/Objects/Object.h"
#include "MantidGeometry/Surfaces/Cylinder.h"
#include "MantidGeometry/Surfaces/Sphere.h"
#include "MantidGeometry/Surfaces/Plane.h"
#include "MantidGeometry/Math/Algebra.h"
#include "MantidGeometry/Surfaces/SurfaceFactory.h"
#include "MantidGeometry/Objects/Track.h"
Nick Draper's avatar
re #843    
Nick Draper committed
21
#include "MantidGeometry/Rendering/GluGeometryHandler.h"
22
23
#include "MantidGeometry/Objects/ShapeFactory.h"

24
25
#include "MantidKernel/Material.h"

26
#include "MantidTestHelpers/ComponentCreationHelper.h"
27

Russell Taylor's avatar
Russell Taylor committed
28
29
using namespace Mantid;
using namespace Geometry;
30
using Mantid::Kernel::V3D;
Russell Taylor's avatar
Russell Taylor committed
31

32
class ObjectTest: public CxxTest::TestSuite
Russell Taylor's avatar
Russell Taylor committed
33
34
35
36
{

public:

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  void testDefaultObjectHasEmptyMaterial()
  {
    Object obj;

    TSM_ASSERT_DELTA("Expected a zero number density",0.0, obj.material().numberDensity(), 1e-12);
  }

  void testObjectSetMaterialReplacesExisting()
  {
    using Mantid::Kernel::Material;
    Object obj;

    TSM_ASSERT_DELTA("Expected a zero number density", 0.0,
                     obj.material().numberDensity(), 1e-12);
    obj.setMaterial(Material("arm", PhysicalConstants::getNeutronAtom(13), 45.0));
    TSM_ASSERT_DELTA("Expected a number density of 45", 45.0,
                     obj.material().numberDensity(), 1e-12);
  }

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
  void testCopyConstructorGivesObjectWithSameAttributes()
  {
    Object_sptr original = ComponentCreationHelper::createSphere(1.0, V3D(), "sphere");
    int objType(-1);
    double radius(-1.0), height(-1.0);
    std::vector<V3D> pts;
    original->GetObjectGeom(objType, pts, radius, height);
    TS_ASSERT_EQUALS(2, objType);
    TS_ASSERT(boost::dynamic_pointer_cast<GluGeometryHandler>(original->getGeometryHandler()));

    Object copy(*original);
    // The copy should be a primitive object with a GluGeometryHandler
    objType = -1;
    copy.GetObjectGeom(objType, pts, radius, height);

    TS_ASSERT_EQUALS(2, objType);
    TS_ASSERT(boost::dynamic_pointer_cast<GluGeometryHandler>(copy.getGeometryHandler()));
    TS_ASSERT_EQUALS(copy.getName(), original->getName());
    // Check the string representation is the same
    TS_ASSERT_EQUALS(copy.str(), original->str());
    TS_ASSERT_EQUALS(copy.getSurfaceIndex(), original->getSurfaceIndex());
  }

  void testAssignmentOperatorGivesObjectWithSameAttributes()
  {
    Object_sptr original = ComponentCreationHelper::createSphere(1.0, V3D(), "sphere");
    int objType(-1);
    double radius(-1.0), height(-1.0);
    std::vector<V3D> pts;
    original->GetObjectGeom(objType, pts, radius, height);
    TS_ASSERT_EQUALS(2, objType);
    TS_ASSERT(boost::dynamic_pointer_cast<GluGeometryHandler>(original->getGeometryHandler()));

    Object lhs; // initialize
    lhs = *original; // assign
    // The copy should be a primitive object with a GluGeometryHandler
    objType = -1;
    lhs.GetObjectGeom(objType, pts, radius, height);

    TS_ASSERT_EQUALS(2, objType);
    TS_ASSERT(boost::dynamic_pointer_cast<GluGeometryHandler>(lhs.getGeometryHandler()));
  }
Russell Taylor's avatar
Russell Taylor committed
98

Nick Draper's avatar
re #843    
Nick Draper committed
99
  void testCreateUnitCube()
Russell Taylor's avatar
Russell Taylor committed
100
  {
101
    Object_sptr geom_obj = createUnitCube();
102

103
    TS_ASSERT_EQUALS(geom_obj->str(),"68 -6 5 -4 3 -2 1");
104
105

    double xmin(0.0), xmax(0.0), ymin(0.0), ymax(0.0), zmin(0.0), zmax(0.0);
106
    geom_obj->getBoundingBox(xmax, ymax, zmax, xmin, ymin, zmin);
107

Russell Taylor's avatar
Russell Taylor committed
108
109
  }

Nick Draper's avatar
re #843    
Nick Draper committed
110
  void testIsOnSideCappedCylinder()
Russell Taylor's avatar
Russell Taylor committed
111
  {
112
    Object_sptr geom_obj = createCappedCylinder();
Russell Taylor's avatar
Russell Taylor committed
113
    //inside
114
115
116
117
118
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,0)),false); //origin
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,2.9,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,-2.9,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,-2.9)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,2.9)),false);
Russell Taylor's avatar
Russell Taylor committed
119
    //on the side
120
121
122
123
124
125
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,3,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,-3,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,-3)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,3)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(1.2,0,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(-3.2,0,0)),true);
Russell Taylor's avatar
Russell Taylor committed
126
127

    //on the edges
128
129
130
131
132
133
134
135
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(1.2,3,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(1.2,-3,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(1.2,0,-3)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(1.2,0,3)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(-3.2,3,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(-3.2,-3,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(-3.2,0,-3)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(-3.2,0,3)),true);
Russell Taylor's avatar
Russell Taylor committed
136
    //out side
137
138
139
140
141
142
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,3.1,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,-3.1,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,-3.1)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,3.1)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(1.3,0,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(-3.3,0,0)),false);
Russell Taylor's avatar
Russell Taylor committed
143
144
145
146
  }

  void testIsValidCappedCylinder()
  {
147
    Object_sptr geom_obj = createCappedCylinder();
Russell Taylor's avatar
Russell Taylor committed
148
    //inside
149
150
151
152
153
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,0)),true); //origin
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,2.9,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,-2.9,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,-2.9)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,2.9)),true);
Russell Taylor's avatar
Russell Taylor committed
154
    //on the side
155
156
157
158
159
160
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,3,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,-3,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,-3)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,3)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(1.2,0,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(-3.2,0,0)),true);
Russell Taylor's avatar
Russell Taylor committed
161
162

    //on the edges
163
164
165
166
167
168
169
170
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(1.2,3,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(1.2,-3,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(1.2,0,-3)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(1.2,0,3)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(-3.2,3,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(-3.2,-3,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(-3.2,0,-3)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(-3.2,0,3)),true);
Russell Taylor's avatar
Russell Taylor committed
171
    //out side
172
173
174
175
176
177
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,3.1,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,-3.1,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,-3.1)),false);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,3.1)),false);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(1.3,0,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(-3.3,0,0)),false);
Russell Taylor's avatar
Russell Taylor committed
178
179
180
181
  }

  void testIsOnSideSphere()
  {
182
    Object_sptr geom_obj = createSphere();
Russell Taylor's avatar
Russell Taylor committed
183
    //inside
184
185
186
187
188
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,0)),false); //origin
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,4.0,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,-4.0,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,-4.0)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,4.0)),false);
Russell Taylor's avatar
Russell Taylor committed
189
    //on the side
190
191
192
193
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,4.1,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,-4.1,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,-4.1)),true);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,4.1)),true);
Russell Taylor's avatar
Russell Taylor committed
194
195

    //out side
196
197
198
199
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,4.2,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,-4.2,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,-4.2)),false);
    TS_ASSERT_EQUALS(geom_obj->isOnSide(V3D(0,0,4.2)),false);
Russell Taylor's avatar
Russell Taylor committed
200
201
202
203
  }

  void testIsValidSphere()
  {
204
    Object_sptr geom_obj = createSphere();
Russell Taylor's avatar
Russell Taylor committed
205
    //inside
206
207
208
209
210
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,0)),true); //origin
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,4.0,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,-4.0,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,-4.0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,4.0)),true);
Russell Taylor's avatar
Russell Taylor committed
211
    //on the side
212
213
214
215
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,4.1,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,-4.1,0)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,-4.1)),true);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,4.1)),true);
Russell Taylor's avatar
Russell Taylor committed
216
217

    //out side
218
219
220
221
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,4.2,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,-4.2,0)),false);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,-4.2)),false);
    TS_ASSERT_EQUALS(geom_obj->isValid(V3D(0,0,4.2)),false);
Russell Taylor's avatar
Russell Taylor committed
222
223
224
225
  }

  void testCalcValidTypeSphere()
  {
226
    Object_sptr geom_obj = createSphere();
Russell Taylor's avatar
Russell Taylor committed
227
    //entry on the normal
228
229
230
231
232
233
234
235
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(-4.1,0,0),V3D(1,0,0)),1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(-4.1,0,0),V3D(-1,0,0)),-1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(4.1,0,0),V3D(1,0,0)),-1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(4.1,0,0),V3D(-1,0,0)),1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(0,-4.1,0),V3D(0,1,0)),1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(0,-4.1,0),V3D(0,-1,0)),-1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(0,4.1,0),V3D(0,1,0)),-1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(0,4.1,0),V3D(0,-1,0)),1);
Russell Taylor's avatar
Russell Taylor committed
236
237

    //a glancing blow
238
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(-4.1,0,0),V3D(0,1,0)),0);
Russell Taylor's avatar
Russell Taylor committed
239
    //not quite on the normal
240
241
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(-4.1,0,0),V3D(0.5,0.5,0)),1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(4.1,0,0),V3D(0.5,0.5,0)),-1);
Russell Taylor's avatar
Russell Taylor committed
242
243
  }

244
245
  void testGetBoundingBoxForSphere()
  {
246
    Object_sptr geom_obj = createSphere();
247
248
249
250
251
252
253
254
255
256
257
258
259
    const double tolerance(1e-10);

    double xmax,ymax,zmax,xmin,ymin,zmin;
    xmax=ymax=zmax=20;
    xmin=ymin=zmin=-20;
    geom_obj->getBoundingBox(xmax,ymax,zmax,xmin,ymin,zmin);
    TS_ASSERT_DELTA(xmax,4.1,tolerance);
    TS_ASSERT_DELTA(ymax,4.1,tolerance);
    TS_ASSERT_DELTA(zmax,4.1,tolerance);
    TS_ASSERT_DELTA(xmin,-4.1,tolerance);
    TS_ASSERT_DELTA(ymin,-4.1,tolerance);
    TS_ASSERT_DELTA(zmin,-4.1,tolerance);

260
261
262
263
264
265
266
267
    const BoundingBox & bbox  = geom_obj->getBoundingBox();

    TS_ASSERT_DELTA(bbox.xMax(),4.1,tolerance);
    TS_ASSERT_DELTA(bbox.yMax(),4.1,tolerance);
    TS_ASSERT_DELTA(bbox.zMax(),4.1,tolerance);
    TS_ASSERT_DELTA(bbox.xMin(),-4.1,tolerance);
    TS_ASSERT_DELTA(bbox.yMin(),-4.1,tolerance);
    TS_ASSERT_DELTA(bbox.zMin(),-4.1,tolerance);
268
269
  }

Russell Taylor's avatar
Russell Taylor committed
270
271
  void testCalcValidTypeCappedCylinder()
  {
272
    Object_sptr geom_obj = createCappedCylinder();
Russell Taylor's avatar
Russell Taylor committed
273
    //entry on the normal
274
275
276
277
278
279
280
281
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(-3.2,0,0),V3D(1,0,0)),1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(-3.2,0,0),V3D(-1,0,0)),-1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(1.2,0,0),V3D(1,0,0)),-1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(1.2,0,0),V3D(-1,0,0)),1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(0,-3,0),V3D(0,1,0)),1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(0,-3,0),V3D(0,-1,0)),-1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(0,3,0),V3D(0,1,0)),-1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(0,3,0),V3D(0,-1,0)),1);
Russell Taylor's avatar
Russell Taylor committed
282
283

    //a glancing blow
284
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(-3.2,0,0),V3D(0,1,0)),0);
Russell Taylor's avatar
Russell Taylor committed
285
    //not quite on the normal
286
287
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(-3.2,0,0),V3D(0.5,0.5,0)),1);
    TS_ASSERT_EQUALS(geom_obj->calcValidType(V3D(1.2,0,0),V3D(0.5,0.5,0)),-1);
Russell Taylor's avatar
Russell Taylor committed
288
289
290
291
  }

  void testInterceptSurfaceSphereZ()
  {
292
    std::vector<Link> expectedResults;
Russell Taylor's avatar
Russell Taylor committed
293
294
295
296
297
298
299
300
    std::string S41="s 1 1 1 4";         // Sphere at (1,1,1) radius 4

    // First create some surfaces
    std::map<int,Surface*> SphSurMap;
    SphSurMap[41]=new Sphere();
    SphSurMap[41]->setSurface(S41);
    SphSurMap[41]->setName(41);

301
    // A sphere
Russell Taylor's avatar
Russell Taylor committed
302
303
    std::string ObjSphere="-41" ;

304
    Object_sptr geom_obj = Object_sptr(new Object);
305
306
    geom_obj->setObject(41,ObjSphere);
    geom_obj->populate(SphSurMap);
Russell Taylor's avatar
Russell Taylor committed
307
308
309
310


    Track track(V3D(-1,1.5,1),V3D(1,0,0));

311
    // format = startPoint, endPoint, total distance so far
Russell Taylor's avatar
Russell Taylor committed
312
    // forward only intercepts means that start point should be track origin
313
    expectedResults.push_back(Link(V3D(-1,1.5,1),
314
      V3D(sqrt(16-0.25)+1,1.5,1.0),sqrt(15.75)+2,*geom_obj));
Russell Taylor's avatar
Russell Taylor committed
315

316
    checkTrackIntercept(geom_obj,track,expectedResults);
Russell Taylor's avatar
Russell Taylor committed
317
318
319
320
  }

  void testInterceptSurfaceSphereY()
  {
321
    std::vector<Link> expectedResults;
322
    Object_sptr geom_obj = createSphere();
Russell Taylor's avatar
Russell Taylor committed
323
324
    Track track(V3D(0,-10,0),V3D(0,1,0));

325
    //format = startPoint, endPoint, total distance so far
326
    expectedResults.push_back(Link(V3D(0,-4.1,0),V3D(0,4.1,0),14.1,*geom_obj));
Russell Taylor's avatar
Russell Taylor committed
327

328
    checkTrackIntercept(geom_obj,track,expectedResults);
Russell Taylor's avatar
Russell Taylor committed
329
330
331
332
  }

  void testInterceptSurfaceSphereX()
  {
333
    std::vector<Link> expectedResults;
334
    Object_sptr geom_obj = createSphere();
Russell Taylor's avatar
Russell Taylor committed
335
    Track track(V3D(-10,0,0),V3D(1,0,0));
336

337
    //format = startPoint, endPoint, total distance so far
338
    expectedResults.push_back(Link(V3D(-4.1,0,0),V3D(4.1,0,0),14.1,*geom_obj));
339
    checkTrackIntercept(geom_obj,track,expectedResults);
Russell Taylor's avatar
Russell Taylor committed
340
341
342
343
  }

  void testInterceptSurfaceCappedCylinderY()
  {
344
    std::vector<Link> expectedResults;
345
    Object_sptr geom_obj = createCappedCylinder();
346
    //format = startPoint, endPoint, total distance so far
347
    expectedResults.push_back(Link(V3D(0,-3,0),V3D(0,3,0),13,*geom_obj));
Russell Taylor's avatar
Russell Taylor committed
348
349

    Track track(V3D(0,-10,0),V3D(0,1,0));
350
    checkTrackIntercept(geom_obj,track,expectedResults);
Russell Taylor's avatar
Russell Taylor committed
351
352
353
354
  }

  void testInterceptSurfaceCappedCylinderX()
  {
355
    std::vector<Link> expectedResults;
356
    Object_sptr geom_obj = createCappedCylinder();
Russell Taylor's avatar
Russell Taylor committed
357
358
    Track track(V3D(-10,0,0),V3D(1,0,0));

359
    //format = startPoint, endPoint, total distance so far
360
    expectedResults.push_back(Link(V3D(-3.2,0,0),V3D(1.2,0,0),11.2,*geom_obj));
361
    checkTrackIntercept(geom_obj,track,expectedResults);
Russell Taylor's avatar
Russell Taylor committed
362
363
364
365
  }

  void testInterceptSurfaceCappedCylinderMiss()
  {
366
    std::vector<Link> expectedResults; //left empty as there are no expected results
367
    Object_sptr geom_obj = createCappedCylinder();
Russell Taylor's avatar
Russell Taylor committed
368
369
    Track track(V3D(-10,0,0),V3D(1,1,0));

370
    checkTrackIntercept(geom_obj,track,expectedResults);
Russell Taylor's avatar
Russell Taylor committed
371
372
  }

373
  void checkTrackIntercept(Track& track, const std::vector<Link>& expectedResults)
Russell Taylor's avatar
Russell Taylor committed
374
375
376
377
  {
    int index = 0;
    for (Track::LType::const_iterator it = track.begin(); it!=track.end();++it)
    {
378
379
      TS_ASSERT_DELTA(it->distFromStart,expectedResults[index].distFromStart,1e-6);
      TS_ASSERT_DELTA(it->distInsideObject,expectedResults[index].distInsideObject,1e-6);
380
      TS_ASSERT_EQUALS(it->componentID,expectedResults[index].componentID);
381
382
      TS_ASSERT_EQUALS(it->entryPoint,expectedResults[index].entryPoint);
      TS_ASSERT_EQUALS(it->exitPoint,expectedResults[index].exitPoint);
Russell Taylor's avatar
Russell Taylor committed
383
384
385
386
387
      ++index;
    }
    TS_ASSERT_EQUALS(index,static_cast<int>(expectedResults.size()));
  }

388
  void checkTrackIntercept(Object_sptr obj, Track& track, const std::vector<Link>& expectedResults)
Russell Taylor's avatar
Russell Taylor committed
389
  {
390
    int unitCount = obj->interceptSurface(track);
391
392
    TS_ASSERT_EQUALS(unitCount,expectedResults.size());
    checkTrackIntercept(track,expectedResults);
Russell Taylor's avatar
Russell Taylor committed
393
394
395
  }

  void xtestTrackTwoIsolatedCubes()
396
    /**
Russell Taylor's avatar
Russell Taylor committed
397
398
399
400
401
    Test a track going through an object
    */
  {
    std::string ObjA="60001 -60002 60003 -60004 60005 -60006";
    std::string ObjB="80001 -80002 60003 -60004 60005 -60006";
402

403
    createSurfaces(ObjA);
Russell Taylor's avatar
Russell Taylor committed
404
405
406
407
    Object object1=Object();
    object1.setObject(3,ObjA);
    object1.populate(SMap);

408
    createSurfaces(ObjB);
Russell Taylor's avatar
Russell Taylor committed
409
410
411
412
    Object object2=Object();
    object2.setObject(4,ObjB);
    object2.populate(SMap);

413
414
    Track TL(Kernel::V3D(-5,0,0),
      Kernel::V3D(1,0,0));
Russell Taylor's avatar
Russell Taylor committed
415
416

    // CARE: This CANNOT be called twice
417
418
    TS_ASSERT(object1.interceptSurface(TL)!=0);
    TS_ASSERT(object2.interceptSurface(TL)!=0);
Russell Taylor's avatar
Russell Taylor committed
419

420
    std::vector<Link> expectedResults;
421
422
    expectedResults.push_back(Link(V3D(-1,0,0),V3D(1,0,0),6,object1));
    expectedResults.push_back(Link(V3D(4.5,0,0),V3D(6.5,0,0),11.5,object2));
Russell Taylor's avatar
Russell Taylor committed
423
424
425
426
427
    checkTrackIntercept(TL,expectedResults);

  }

  void testTrackTwoTouchingCubes()
428
    /**
Russell Taylor's avatar
Russell Taylor committed
429
430
431
432
433
434
    Test a track going through an object
    */
  {
    std::string ObjA="60001 -60002 60003 -60004 60005 -60006";
    std::string ObjB="60002 -80002 60003 -60004 60005 -60006";

435
    createSurfaces(ObjA);
Russell Taylor's avatar
Russell Taylor committed
436
437
438
439
    Object object1=Object();
    object1.setObject(3,ObjA);
    object1.populate(SMap);

440
    createSurfaces(ObjB);
Russell Taylor's avatar
Russell Taylor committed
441
442
443
444
    Object object2=Object();
    object2.setObject(4,ObjB);
    object2.populate(SMap);

445
    Track TL(Kernel::V3D(-5,0,0), Kernel::V3D(1,0,0));
Russell Taylor's avatar
Russell Taylor committed
446
447

    // CARE: This CANNOT be called twice
448
449
    TS_ASSERT(object1.interceptSurface(TL)!=0);
    TS_ASSERT(object2.interceptSurface(TL)!=0);
Russell Taylor's avatar
Russell Taylor committed
450

451
    std::vector<Link> expectedResults;
452
453
    expectedResults.push_back(Link(V3D(-1,0,0),V3D(1,0,0),6, object1));
    expectedResults.push_back(Link(V3D(1,0,0),V3D(6.5,0,0),11.5, object2));
Russell Taylor's avatar
Russell Taylor committed
454
455
456
457
458
459

    checkTrackIntercept(TL,expectedResults);

  }

  void testTrackCubeWithInternalSphere()
460
    /**
Russell Taylor's avatar
Russell Taylor committed
461
462
463
464
465
466
    Test a track going through an object
    */
  {
    std::string ObjA="60001 -60002 60003 -60004 60005 -60006 71";
    std::string ObjB="-71";

467
    createSurfaces(ObjA);
Russell Taylor's avatar
Russell Taylor committed
468
469
470
471
    Object object1=Object();
    object1.setObject(3,ObjA);
    object1.populate(SMap);

472
    createSurfaces(ObjB);
Russell Taylor's avatar
Russell Taylor committed
473
474
475
476
    Object object2=Object();
    object2.setObject(4,ObjB);
    object2.populate(SMap);

477
478
    Track TL(Kernel::V3D(-5,0,0),
      Kernel::V3D(1,0,0));
Russell Taylor's avatar
Russell Taylor committed
479
480
481
482
483

    // CARE: This CANNOT be called twice
    TS_ASSERT(object1.interceptSurface(TL)!=0);
    TS_ASSERT(object2.interceptSurface(TL)!=0);

484
    std::vector<Link> expectedResults;
485
486
487
    expectedResults.push_back(Link(V3D(-1,0,0),V3D(-0.8,0,0),4.2,object1));
    expectedResults.push_back(Link(V3D(-0.8,0,0),V3D(0.8,0,0),5.8,object1));
    expectedResults.push_back(Link(V3D(0.8,0,0),V3D(1,0,0),6,object2));
Russell Taylor's avatar
Russell Taylor committed
488
489
490
491
    checkTrackIntercept(TL,expectedResults);
  }

  void testTrack_CubePlusInternalEdgeTouchSpheres()
492
    /**
Russell Taylor's avatar
Russell Taylor committed
493
494
495
496
497
    Test a track going through an object
    */
  {
    std::string ObjA="60001 -60002 60003 -60004 60005 -60006 72 73";
    std::string ObjB="(-72 : -73)";
498

499
    createSurfaces(ObjA);
Russell Taylor's avatar
Russell Taylor committed
500
501
502
503
    Object object1=Object();
    object1.setObject(3,ObjA);
    object1.populate(SMap);

504
    createSurfaces(ObjB);
Russell Taylor's avatar
Russell Taylor committed
505
506
507
508
    Object object2=Object();
    object2.setObject(4,ObjB);
    object2.populate(SMap);

509
    Track TL(Kernel::V3D(-5,0,0), Kernel::V3D(1,0,0));
Russell Taylor's avatar
Russell Taylor committed
510
511
512
513
514
515


    // CARE: This CANNOT be called twice
    TS_ASSERT(object1.interceptSurface(TL)!=0);
    TS_ASSERT(object2.interceptSurface(TL)!=0);

516
    std::vector<Link> expectedResults;
517
518
519
    expectedResults.push_back(Link(V3D(-1,0,0),V3D(-0.4,0,0),4.6,object1));
    expectedResults.push_back(Link(V3D(-0.4,0,0),V3D(0.2,0,0),5.2,object1));
    expectedResults.push_back(Link(V3D(0.2,0,0),V3D(1,0,0),6,object2));
Russell Taylor's avatar
Russell Taylor committed
520
521
522
523
    checkTrackIntercept(TL,expectedResults);
  }

  void testTrack_CubePlusInternalEdgeTouchSpheresMiss()
524
    /**
Russell Taylor's avatar
Russell Taylor committed
525
526
527
528
529
    Test a track missing an object
    */
  {
    std::string ObjA="60001 -60002 60003 -60004 60005 -60006 72 73";
    std::string ObjB="(-72 : -73)";
530

531
    createSurfaces(ObjA);
Russell Taylor's avatar
Russell Taylor committed
532
533
534
535
    Object object1=Object();
    object1.setObject(3,ObjA);
    object1.populate(SMap);

536
    createSurfaces(ObjB);
Russell Taylor's avatar
Russell Taylor committed
537
538
539
540
    Object object2=Object();
    object2.setObject(4,ObjB);
    object2.populate(SMap);

541
542
    Track TL(Kernel::V3D(-5,0,0),
      Kernel::V3D(0,1,0));
Russell Taylor's avatar
Russell Taylor committed
543
544
545
546
547
548


    // CARE: This CANNOT be called twice
    TS_ASSERT_EQUALS(object1.interceptSurface(TL),0);
    TS_ASSERT_EQUALS(object2.interceptSurface(TL),0);

549
    std::vector<Link> expectedResults; //left empty as this should miss
Russell Taylor's avatar
Russell Taylor committed
550
551
552
553
    checkTrackIntercept(TL,expectedResults);
  }

  void testFindPointInCube()
554
    /**
Russell Taylor's avatar
Russell Taylor committed
555
556
557
    Test find point in cube
    */
  {
558
    Object_sptr geom_obj = createUnitCube();
Russell Taylor's avatar
Russell Taylor committed
559
    // initial guess in object
560
    Kernel::V3D pt;
561
    TS_ASSERT_EQUALS(geom_obj->getPointInObject(pt),1);
Russell Taylor's avatar
Russell Taylor committed
562
563
564
565
566
567
    TS_ASSERT_EQUALS(pt,V3D(0,0,0));
    // initial guess not in object, but on x-axis
    std::vector<std::string> planes;
    planes.push_back("px 10"); planes.push_back("px 11");
    planes.push_back("py -0.5"); planes.push_back("py 0.5");
    planes.push_back("pz -0.5"); planes.push_back("pz 0.5");
568
569
    Object_sptr B =createCuboid(planes);
    TS_ASSERT_EQUALS(B->getPointInObject(pt),1);
Russell Taylor's avatar
Russell Taylor committed
570
571
572
573
574
575
    TS_ASSERT_EQUALS(pt,V3D(10,0,0));
    // on y axis
    planes.clear();
    planes.push_back("px -0.5"); planes.push_back("px 0.5");
    planes.push_back("py -22"); planes.push_back("py -21");
    planes.push_back("pz -0.5"); planes.push_back("pz 0.5");
576
577
    Object_sptr C =createCuboid(planes);
    TS_ASSERT_EQUALS(C->getPointInObject(pt),1);
Russell Taylor's avatar
Russell Taylor committed
578
579
580
581
582
583
    TS_ASSERT_EQUALS(pt,V3D(0,-21,0));
    // not on principle axis, now works using getBoundingBox
    planes.clear();
    planes.push_back("px 0.5"); planes.push_back("px 1.5");
    planes.push_back("py -22"); planes.push_back("py -21");
    planes.push_back("pz -0.5"); planes.push_back("pz 0.5");
584
585
    Object_sptr D =createCuboid(planes);
    TS_ASSERT_EQUALS(D->getPointInObject(pt),1);
Russell Taylor's avatar
Russell Taylor committed
586
587
588
589
590
591
592
593
594
595
596
597
    TS_ASSERT_DELTA(pt.X(),1.0,1e-6);
    TS_ASSERT_DELTA(pt.Y(),-21.5,1e-6);
    TS_ASSERT_DELTA(pt.Z(),0.0,1e-6);
    planes.clear();
    // Test non axis aligned (AA) case - getPointInObject works because the object is on a principle axis
    // However, if not on a principle axis then the getBoundingBox fails to find correct minima (maxima are OK)
    // This is related to use of the complement for -ve surfaces and might be avoided by only using +ve surfaces
    // for defining non-AA objects. However, BoundingBox is poor for non-AA and needs improvement if these are
    // common
    planes.push_back("p 1 0 0 -0.5"); planes.push_back("p 1 0 0 0.5");
    planes.push_back("p 0 .70710678118 .70710678118 -1.1"); planes.push_back("p 0 .70710678118 .70710678118 -0.1");
    planes.push_back("p 0 -.70710678118 .70710678118 -0.5"); planes.push_back("p 0 -.70710678118 .70710678118 0.5");
598
599
    Object_sptr E =createCuboid(planes);
    TS_ASSERT_EQUALS(E->getPointInObject(pt),1);
Russell Taylor's avatar
Russell Taylor committed
600
601
602
603
604
605
606
607
608
609
610
    TS_ASSERT_DELTA(pt.X(),0.0,1e-6);
    TS_ASSERT_DELTA(pt.Y(),-0.1414213562373,1e-6);
    TS_ASSERT_DELTA(pt.Z(),0.0,1e-6);
    planes.clear();
    // This test fails to find a point in object, as object not on a principle axis
    // and getBoundingBox does not give a useful result in this case.
    // Object is unit cube located at +-0.5 in x but centred on z=y=-1.606.. and rotated 45deg
    // to these two axes
    planes.push_back("p 1 0 0 -0.5"); planes.push_back("p 1 0 0 0.5");
    planes.push_back("p 0  .70710678118 .70710678118 -2"); planes.push_back("p 0  .70710678118 .70710678118 -1");
    planes.push_back("p 0 -.70710678118 .70710678118 -0.5"); planes.push_back("p 0 -.70710678118 .70710678118 0.5");
611
612
    Object_sptr F =createCuboid(planes);
    TS_ASSERT_EQUALS(F->getPointInObject(pt),0);
Russell Taylor's avatar
Russell Taylor committed
613
    // Test use of defineBoundingBox to explictly set the bounding box, when the automatic method fails
614
    F->defineBoundingBox(0.5,-1/(2.0*sqrt(2.0)),-1.0/(2.0*sqrt(2.0)),
Russell Taylor's avatar
Russell Taylor committed
615
      -0.5,-sqrt(2.0)-1.0/(2.0*sqrt(2.0)),-sqrt(2.0)-1.0/(2.0*sqrt(2.0)));
616
617
618
    TS_ASSERT_EQUALS(F->getPointInObject(pt),1);
    Object_sptr S = createSphere();
    TS_ASSERT_EQUALS(S->getPointInObject(pt),1);
Russell Taylor's avatar
Russell Taylor committed
619
620
621
622
623
    TS_ASSERT_EQUALS(pt,V3D(0.0,0.0,0));
  }


  void testSolidAngleSphere()
624
    /**
Russell Taylor's avatar
Russell Taylor committed
625
626
627
    Test solid angle calculation for a sphere
    */
  {
628
    Object_sptr geom_obj = createSphere();
Russell Taylor's avatar
Russell Taylor committed
629
630
631
632
633
634
    double satol=2e-2; // tolerance for solid angle

    // Solid angle at distance 8.1 from centre of sphere radius 4.1 x/y/z
    // Expected solid angle calculated values from sa=2pi(1-cos(arcsin(R/r))
    // where R is sphere radius and r is distance of observer from sphere centre
    // Intercept for track in reverse direction now worked round
635
    TS_ASSERT_DELTA(geom_obj->rayTraceSolidAngle(V3D(8.1,0,0)),0.864364,satol);
Russell Taylor's avatar
Russell Taylor committed
636
    // internal point (should be 4pi)
637
    TS_ASSERT_DELTA(geom_obj->rayTraceSolidAngle(V3D(0,0,0)),4*M_PI,satol);
Russell Taylor's avatar
Russell Taylor committed
638
    // surface point
639
    TS_ASSERT_DELTA(geom_obj->rayTraceSolidAngle(V3D(4.1,0,0)),2*M_PI,satol);
Russell Taylor's avatar
Russell Taylor committed
640
641
  }

642

Russell Taylor's avatar
Russell Taylor committed
643
  void testSolidAngleCappedCylinder()
644
    /**
Russell Taylor's avatar
Russell Taylor committed
645
646
647
    Test solid angle calculation for a capped cylinder
    */
  {
648
    Object_sptr geom_obj = createSmallCappedCylinder();
649
    // Want to test triangulation so setup a geometry handler
650
    boost::shared_ptr<GluGeometryHandler> h = boost::shared_ptr<GluGeometryHandler>(new GluGeometryHandler(geom_obj.get()));
651
    h->setCylinder(V3D(-0.0015,0.0,0.0), V3D(1., 0.0, 0.0), 0.005, 0.003);
652
    geom_obj->setGeometryHandler(h);
653

654
    double satol(1e-8); // tolerance for solid angle
Russell Taylor's avatar
Russell Taylor committed
655

656
    // solid angle at point -0.5 from capped cyl -1.0 -0.997 in x, rad 0.005 - approx WISH cylinder
657
658
    // We intentionally exclude the cylinder end caps so they this should produce 0
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(-0.5, 0.0, 0.0)), 0.0, satol);
659
    // Other end
660
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(-1.497, 0.0, 0.0)), 0.0, satol);
661

662
663
664
665
666
    // Side values
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(0, 0, 0.1)), 0.00301186, satol);
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(0, 0, -0.1)), 0.00301186, satol);
    // Sweep in the axis of the cylinder angle to see if the solid angle decreases (as we are excluding the end caps)
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(0.1, 0.0, 0.1)), 0.00100267, satol);
667

Russell Taylor's avatar
Russell Taylor committed
668
    // internal point (should be 4pi)
669
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(-0.999, 0.0, 0.0)),4*M_PI,satol);
670
671

    // surface points
672
673
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(-1.0, 0.0, 0.0)),2*M_PI,satol);
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(-0.997, 0.0, 0.0)),2*M_PI,satol);
674

Russell Taylor's avatar
Russell Taylor committed
675
676
  }

677

Russell Taylor's avatar
Russell Taylor committed
678
  void testSolidAngleCubeTriangles()
679
    /**
Russell Taylor's avatar
Russell Taylor committed
680
681
682
683
    Test solid angle calculation for a cube using triangles
    - test for using Open Cascade surface triangulation for all solid angles.
    */
  {
684
    Object_sptr geom_obj = createUnitCube();
Russell Taylor's avatar
Russell Taylor committed
685
686
687
688
689
690
    double satol=1e-3; // tolerance for solid angle

    // solid angle at distance 0.5 should be 4pi/6 by symmetry
    //
    // tests for Triangulated cube
    //
691
692
693
694
695
696
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(1.0,0,0)),M_PI*2.0/3.0,satol);
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(-1.0,0,0)),M_PI*2.0/3.0,satol);
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(0,1.0,0)),M_PI*2.0/3.0,satol);
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(0,-1.0,0)),M_PI*2.0/3.0,satol);
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(0,0,1.0)),M_PI*2.0/3.0,satol);
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(0,0,-1.0)),M_PI*2.0/3.0,satol);
Russell Taylor's avatar
Russell Taylor committed
697
698
  }

699
700
701
702
703
704
705
706
707
708
709
710
711
712


  /** Add a scale factor */
  void testSolidAngleCubeTriangles_WithScaleFactor()
  {
    Object_sptr geom_obj = createUnitCube();
    double satol=1e-3; // tolerance for solid angle
    // solid angle at distance 0.5 should be 4pi/6 by symmetry
    double expected = M_PI*2.0/3.0;
    V3D scaleFactor(2.0,2.0,2.0);
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(2.0,0,0), scaleFactor),expected,satol);
  }


713
  void testGetBoundingBoxForCylinder()
714
    /**
Russell Taylor's avatar
Russell Taylor committed
715
716
717
    Test bounding box for a object capped cylinder
    */
  {
718
    Object_sptr geom_obj = createCappedCylinder();
Russell Taylor's avatar
Russell Taylor committed
719
720
721
    double xmax,ymax,zmax,xmin,ymin,zmin;
    xmax=ymax=zmax=100;
    xmin=ymin=zmin=-100;
722
    geom_obj->getBoundingBox(xmax,ymax,zmax,xmin,ymin,zmin);
Russell Taylor's avatar
Russell Taylor committed
723
724
725
726
727
728
729
730
    TS_ASSERT_DELTA(xmax,1.2,0.0001);
    TS_ASSERT_DELTA(ymax,3.0,0.0001);
    TS_ASSERT_DELTA(zmax,3.0,0.0001);
    TS_ASSERT_DELTA(xmin,-3.2,0.0001);
    TS_ASSERT_DELTA(ymin,-3.0,0.0001);
    TS_ASSERT_DELTA(zmin,-3.0,0.0001);
  }

731
  void testdefineBoundingBox()
732
    /**
Russell Taylor's avatar
Russell Taylor committed
733
734
735
    Test use of defineBoundingBox
    */
  {
736
    Object_sptr geom_obj = createCappedCylinder();
Russell Taylor's avatar
Russell Taylor committed
737
738
739
    double xmax,ymax,zmax,xmin,ymin,zmin;
    xmax=1.2;ymax=3.0;zmax=3.0;
    xmin=-3.2;ymin=-3.0;zmin=-3.0;
740
741

    TS_ASSERT_THROWS_NOTHING(geom_obj->defineBoundingBox(xmax,ymax,zmax,xmin,ymin,zmin));
742

743
    const BoundingBox & boundBox = geom_obj->getBoundingBox();
744

745
746
747
748
749
750
    TS_ASSERT_EQUALS(boundBox.xMax(),1.2);
    TS_ASSERT_EQUALS(boundBox.yMax(),3.0);
    TS_ASSERT_EQUALS(boundBox.zMax(),3.0);
    TS_ASSERT_EQUALS(boundBox.xMin(),-3.2);
    TS_ASSERT_EQUALS(boundBox.yMin(),-3.0);
    TS_ASSERT_EQUALS(boundBox.zMin(),-3.0);
751
752

    //Inconsistent bounding box
Russell Taylor's avatar
Russell Taylor committed
753
    xmax=1.2;xmin=3.0;
754
    TS_ASSERT_THROWS(geom_obj->defineBoundingBox(xmax,ymax,zmax,xmin,ymin,zmin),std::invalid_argument);
Russell Taylor's avatar
Russell Taylor committed
755
756
757

  }
  void testSurfaceTriangulation()
758
    /**
Russell Taylor's avatar
Russell Taylor committed
759
760
761
    Test triangle solid angle calc
    */
  {
762
    Object_sptr geom_obj = createCappedCylinder();
Russell Taylor's avatar
Russell Taylor committed
763
764
765
    double xmax,ymax,zmax,xmin,ymin,zmin;
    xmax=20;ymax=20.0;zmax=20.0;
    xmin=-20.0;ymin=-20.0;zmin=-20.0;
766
    geom_obj->getBoundingBox(xmax,ymax,zmax,xmin,ymin,zmin);
Russell Taylor's avatar
Russell Taylor committed
767
768
    double saTri,saRay;
    V3D observer(4.2,0,0);
769

Russell Taylor's avatar
Russell Taylor committed
770
771
    double satol=1e-3; // typical result tolerance

772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
//    if(timeTest)
//    {
//      // block to test time of solid angle methods
//      // change false to true to include
//      int iter=4000;
//      int starttime=clock();
//      for (int i=0;i<iter;i++)
//        saTri=geom_obj->triangleSolidAngle(observer);
//      int endtime=clock();
//      std::cout << std::endl << "Cyl tri time=" << (endtime-starttime)/(static_cast<double>(CLOCKS_PER_SEC*iter)) << std::endl;
//      iter=50;
//      starttime=clock();
//      for (int i=0;i<iter;i++)
//        saRay=geom_obj->rayTraceSolidAngle(observer);
//      endtime=clock();
//      std::cout << "Cyl ray time=" << (endtime-starttime)/(static_cast<double>(CLOCKS_PER_SEC*iter)) << std::endl;
//    }
Russell Taylor's avatar
Russell Taylor committed
789

790
791
    saTri=geom_obj->triangleSolidAngle(observer);
    saRay=geom_obj->rayTraceSolidAngle(observer);
Russell Taylor's avatar
Russell Taylor committed
792
793
    TS_ASSERT_DELTA(saTri,1.840302,0.001);
    TS_ASSERT_DELTA(saRay,1.840302,0.01);
794

Russell Taylor's avatar
Russell Taylor committed
795
    observer=V3D(-7.2,0,0);
796
797
    saTri=geom_obj->triangleSolidAngle(observer);
    saRay=geom_obj->rayTraceSolidAngle(observer);
798

Russell Taylor's avatar
Russell Taylor committed
799
800
801
802
    TS_ASSERT_DELTA(saTri,1.25663708,0.001);
    TS_ASSERT_DELTA(saRay,1.25663708,0.001);

    // No analytic value for side on SA, using hi-res value
803
804
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(0,0,7)),0.7531,0.753*satol);
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(0,7,0)),0.7531,0.753*satol);
Russell Taylor's avatar
Russell Taylor committed
805

806
    saTri=geom_obj->triangleSolidAngle(V3D(20,0,0));
Russell Taylor's avatar
Russell Taylor committed
807
    TS_ASSERT_DELTA(saTri,0.07850147,satol*0.0785);
808
    saTri=geom_obj->triangleSolidAngle(V3D(200,0,0));
Russell Taylor's avatar
Russell Taylor committed
809
    TS_ASSERT_DELTA(saTri,0.000715295,satol*0.000715);
810
    saTri=geom_obj->triangleSolidAngle(V3D(2000,0,0));
Russell Taylor's avatar
Russell Taylor committed
811
    TS_ASSERT_DELTA(saTri,7.08131e-6,satol*7.08e-6);
812

Russell Taylor's avatar
Russell Taylor committed
813
814
  }
  void testSolidAngleSphereTri()
815
    /**
Russell Taylor's avatar
Russell Taylor committed
816
817
818
    Test solid angle calculation for a sphere from triangulation
    */
  {
819
    Object_sptr geom_obj = createSphere();
Russell Taylor's avatar
Russell Taylor committed
820
821
822
823
824
825
    double satol=1e-3; // tolerance for solid angle

    // Solid angle at distance 8.1 from centre of sphere radius 4.1 x/y/z
    // Expected solid angle calculated values from sa=2pi(1-cos(arcsin(R/r))
    // where R is sphere radius and r is distance of observer from sphere centre
    // Intercept for track in reverse direction now worked round
826
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(8.1,0,0)),0.864364,satol);
Russell Taylor's avatar
Russell Taylor committed
827
    // internal point (should be 4pi)
828
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(0,0,0)),4*M_PI,satol);
Russell Taylor's avatar
Russell Taylor committed
829
    // surface point
830
    TS_ASSERT_DELTA(geom_obj->triangleSolidAngle(V3D(4.1,0,0)),2*M_PI,satol);
Russell Taylor's avatar
Russell Taylor committed
831
832
833
834
835
  }

private:

  /// Surface type
836
  typedef std::map<int,Surface*> STYPE ;
Russell Taylor's avatar
Russell Taylor committed
837
838
839

  /// set timeTest true to get time comparisons of soild angle methods
  const static bool timeTest=false;
840

Russell Taylor's avatar
Russell Taylor committed
841
842
  STYPE SMap;   ///< Surface Map

843
  Object_sptr createCappedCylinder()
Russell Taylor's avatar
Russell Taylor committed
844
845
846
847
848
849
850
851
852
853
854
855
  {
    std::string C31="cx 3.0";         // cylinder x-axis radius 3
    std::string C32="px 1.2";
    std::string C33="px -3.2";

    // First create some surfaces
    std::map<int,Surface*> CylSurMap;
    CylSurMap[31]=new Cylinder();
    CylSurMap[32]=new Plane();
    CylSurMap[33]=new Plane();

    CylSurMap[31]->setSurface(C31);
856
857
858
859
860
861
    CylSurMap[32]->setSurface(C32);
    CylSurMap[33]->setSurface(C33);
    CylSurMap[31]->setName(31);
    CylSurMap[32]->setName(32);
    CylSurMap[33]->setName(33);

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

866
    Object_sptr retVal = Object_sptr(new Object);
867
868
869
    retVal->setObject(21,ObjCapCylinder);
    retVal->populate(CylSurMap);

870
    TS_ASSERT(retVal.get());
871
872
873

    return retVal;
  }
874

875
876
  // This creates a cylinder to test the solid angle that is more realistic in size
  // for a detector cylinder
877
  Object_sptr createSmallCappedCylinder()
878
879
880
881
882
883
884
885
886
887
888
889
  {
    std::string C31="cx 0.005";         // cylinder x-axis radius 0.005 and height 0.003
    std::string C32="px -0.997";
    std::string C33="px -1.0";

    // First create some surfaces
    std::map<int,Surface*> CylSurMap;
    CylSurMap[31]=new Cylinder();
    CylSurMap[32]=new Plane();
    CylSurMap[33]=new Plane();

    CylSurMap[31]->setSurface(C31);
Russell Taylor's avatar
Russell Taylor committed
890
891
892
893
894
895
    CylSurMap[32]->setSurface(C32);
    CylSurMap[33]->setSurface(C33);
    CylSurMap[31]->setName(31);
    CylSurMap[32]->setName(32);
    CylSurMap[33]->setName(33);

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

900
    Object_sptr retVal = Object_sptr(new Object);
901
902
    retVal->setObject(21,ObjCapCylinder);
    retVal->populate(CylSurMap);
Russell Taylor's avatar
Russell Taylor committed
903
904
905
906

    return retVal;
  }

907
  Object_sptr createSphere()
Russell Taylor's avatar
Russell Taylor committed
908
909
910
911
912
913
914
915
916
  {
    std::string S41="so 4.1";         // Sphere at origin radius 4.1

    // First create some surfaces
    std::map<int,Surface*> SphSurMap;
    SphSurMap[41]=new Sphere();
    SphSurMap[41]->setSurface(S41);
    SphSurMap[41]->setName(41);

917
    // A sphere
Russell Taylor's avatar
Russell Taylor committed
918
919
    std::string ObjSphere="-41" ;

920
    Object_sptr retVal = Object_sptr(new Object);
921
922
    retVal->setObject(41,ObjSphere);
    retVal->populate(SphSurMap);
Russell Taylor's avatar
Russell Taylor committed
923
924
925
926
927

    return retVal;
  }

  void clearSurfMap()
928
    /**
Russell Taylor's avatar
Russell Taylor committed
929
930
931
932
    Clears the surface map for a new test
    or destruction.
    */
  {
933
    SMap.clear();
Russell Taylor's avatar
Russell Taylor committed
934
935
936
    return;
  }

937
  void createSurfaces(const std::string& desired)
938
    /**
Russell Taylor's avatar
Russell Taylor committed
939
940
941
942
943
944
945
946
947
948
    Creates a list of surfaces for used in the objects
    and populates the MObj layers.
    */
  {
    clearSurfMap();

    // PLANE SURFACES:

    typedef std::pair<int,std::string> SCompT;
    std::vector<SCompT> SurfLine;
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
    if (desired.find("60001") != std::string::npos)
      SurfLine.push_back(SCompT(60001,"px -1"));
    if (desired.find("60002") != std::string::npos)
      SurfLine.push_back(SCompT(60002,"px 1"));
    if (desired.find("60003") != std::string::npos)
      SurfLine.push_back(SCompT(60003,"py -2"));
    if (desired.find("60004") != std::string::npos)
      SurfLine.push_back(SCompT(60004,"py 2"));
    if (desired.find("60005") != std::string::npos)
      SurfLine.push_back(SCompT(60005,"pz -3"));
    if (desired.find("60006") != std::string::npos)
      SurfLine.push_back(SCompT(60006,"pz 3"));

    if (desired.find("80001") != std::string::npos)
      SurfLine.push_back(SCompT(80001,"px 4.5"));
    if (desired.find("80002") != std::string::npos)
      SurfLine.push_back(SCompT(80002,"px 6.5"));

    if (desired.find("71") != std::string::npos)
      SurfLine.push_back(SCompT(71,"so 0.8"));
    if (desired.find("72") != std::string::npos)
      SurfLine.push_back(SCompT(72,"s -0.7 0 0 0.3"));
    if (desired.find("73") != std::string::npos)
      SurfLine.push_back(SCompT(73,"s 0.6 0 0 0.4"));
Russell Taylor's avatar
Russell Taylor committed
973
974
975
976
977
978

    std::vector<SCompT>::const_iterator vc;

    // Note that the testObject now manages the "new Plane"
    Geometry::Surface* A;
    for(vc=SurfLine.begin();vc!=SurfLine.end();vc++)
979
    {
Russell Taylor's avatar
Russell Taylor committed
980
981
982
983
984
985
986
987
988
989
990
991
992
993
      A=Geometry::SurfaceFactory::Instance()->processLine(vc->second);
      if (!A)
      {
        std::cerr<<"Failed to process line "<<vc->second<<std::endl;
        exit(1);
      }
      A->setName(vc->first);
      SMap.insert(STYPE::value_type(vc->first,A));
    }

    return;
  }


994
  Object_sptr createUnitCube()
Russell Taylor's avatar
Russell Taylor committed
995
996
997
998
999
1000
  {
    std::string C1="px -0.5";         // cube +/-0.5
    std::string C2="px 0.5";
    std::string C3="py -0.5";
    std::string C4="py 0.5";
    std::string C5="pz -0.5";